From 5affdaafce7d43e4a719046832dc3556090d8da3 Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Sun, 29 Mar 2020 00:21:48 -0400 Subject: [PATCH 01/12] Implement gen-doc-urls --- github/actions_workflow_jobs.go | 2 +- github/activity_events.go | 8 +- github/activity_notifications.go | 10 +- github/activity_star.go | 8 +- github/activity_watching.go | 2 +- github/apps.go | 8 +- github/apps_installation.go | 4 +- github/apps_marketplace.go | 2 +- github/checks.go | 14 +- github/gen-doc-urls.go | 823 ++++++++ github/gen-doc-urls_test.go | 3143 ++++++++++++++++++++++++++++++ github/gists.go | 10 +- github/issues.go | 8 +- github/issues_comments.go | 2 +- github/migrations.go | 12 +- github/migrations_user.go | 2 +- github/orgs.go | 4 +- github/orgs_members.go | 4 +- github/pulls.go | 2 +- github/pulls_comments.go | 4 +- github/reactions.go | 12 +- github/repos.go | 20 +- github/repos_collaborators.go | 4 +- github/repos_commits.go | 4 +- github/repos_community_health.go | 2 +- github/repos_contents.go | 4 +- github/repos_hooks.go | 2 +- github/repos_keys.go | 8 +- github/repos_pages.go | 4 +- github/repos_stats.go | 10 +- github/repos_traffic.go | 2 +- github/search.go | 2 +- github/teams.go | 12 +- github/users_gpg_keys.go | 2 +- github/users_keys.go | 2 +- 35 files changed, 4064 insertions(+), 98 deletions(-) create mode 100644 github/gen-doc-urls.go create mode 100644 github/gen-doc-urls_test.go diff --git a/github/actions_workflow_jobs.go b/github/actions_workflow_jobs.go index 8cb7c6aa876..0838ce48d74 100644 --- a/github/actions_workflow_jobs.go +++ b/github/actions_workflow_jobs.go @@ -84,7 +84,7 @@ func (s *ActionsService) ListWorkflowJobs(ctx context.Context, owner, repo strin // GetWorkflowJobByID gets a specific job in a workflow run by ID. // -// GitHub API docs: https://developer.github.com/v3/actions/workflow_jobs/#list-jobs-for-a-workflow-run +// GitHub API docs: https://developer.github.com/v3/actions/workflow_jobs/#get-a-workflow-job 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) diff --git a/github/activity_events.go b/github/activity_events.go index 115bcc97d3a..38f1d98c88b 100644 --- a/github/activity_events.go +++ b/github/activity_events.go @@ -107,7 +107,7 @@ func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, r // 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, opts *ListOptions) ([]*Event, *Response, error) { u := fmt.Sprintf("orgs/%v/events", org) u, err := addOptions(u, opts) @@ -132,7 +132,7 @@ func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org str // ListEventsPerformedByUser lists the events performed by a user. If publicOnly is // 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-public-events-for-a-user func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) { var u string if publicOnly { @@ -162,7 +162,7 @@ func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user st // ListEventsReceivedByUser lists the events received by a user. If publicOnly is // 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-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 if publicOnly { @@ -192,7 +192,7 @@ func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user str // ListUserEventsForOrganization provides the user’s organization dashboard. You // 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, opts *ListOptions) ([]*Event, *Response, error) { u := fmt.Sprintf("users/%v/events/orgs/%v", user, org) u, err := addOptions(u, opts) diff --git a/github/activity_notifications.go b/github/activity_notifications.go index 983da6f82f1..9c19922bb30 100644 --- a/github/activity_notifications.go +++ b/github/activity_notifications.go @@ -49,7 +49,7 @@ type NotificationListOptions struct { // 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, opts *NotificationListOptions) ([]*Notification, *Response, error) { u := fmt.Sprintf("notifications") u, err := addOptions(u, opts) @@ -74,7 +74,7 @@ func (s *ActivityService) ListNotifications(ctx context.Context, opts *Notificat // ListRepositoryNotifications lists all notifications in a given repository // 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, opts *NotificationListOptions) ([]*Notification, *Response, error) { u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) u, err := addOptions(u, opts) @@ -118,7 +118,7 @@ func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead ti // MarkRepositoryNotificationsRead marks all notifications up to lastRead in // 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) { opts := &markReadOptions{ LastReadAt: lastRead, @@ -134,7 +134,7 @@ func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, o // 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) { 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 // 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) { u := fmt.Sprintf("notifications/threads/%v/subscription", id) diff --git a/github/activity_star.go b/github/activity_star.go index 1e9850f9e13..7f526e3aebe 100644 --- a/github/activity_star.go +++ b/github/activity_star.go @@ -67,7 +67,7 @@ type ActivityListStarredOptions struct { // ListStarred lists all the repos starred by a user. Passing the empty string // 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-the-authenticated-useruser func (s *ActivityService) ListStarred(ctx context.Context, user string, opts *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) { var u string if user != "" { @@ -100,7 +100,7 @@ func (s *ActivityService) ListStarred(ctx context.Context, user string, opts *Ac // 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) { u := fmt.Sprintf("user/starred/%v/%v", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -114,7 +114,7 @@ func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bo // 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) { u := fmt.Sprintf("user/starred/%v/%v", owner, repo) req, err := s.client.NewRequest("PUT", u, nil) @@ -126,7 +126,7 @@ func (s *ActivityService) Star(ctx context.Context, owner, repo string) (*Respon // 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) { u := fmt.Sprintf("user/starred/%v/%v", owner, repo) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/github/activity_watching.go b/github/activity_watching.go index 608647a6ce5..4ff1a91b246 100644 --- a/github/activity_watching.go +++ b/github/activity_watching.go @@ -52,7 +52,7 @@ func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, // ListWatched lists the repositories the specified user is watching. Passing // 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-the-authenticated-useruser func (s *ActivityService) ListWatched(ctx context.Context, user string, opts *ListOptions) ([]*Repository, *Response, error) { var u string if user != "" { diff --git a/github/apps.go b/github/apps.go index 75d9177fa9a..9ffcfc45310 100644 --- a/github/apps.go +++ b/github/apps.go @@ -123,7 +123,7 @@ func (i Installation) String() string { // 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 +// GitHub API docs: https://developer.github.com/v3/apps/#get-the-authenticated-github-app func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) { var u string if appSlug != "" { @@ -177,14 +177,14 @@ func (s *AppsService) ListInstallations(ctx context.Context, opts *ListOptions) // GetInstallation returns the specified installation. // -// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-installation +// GitHub API docs: https://developer.github.com/v3/apps/#get-an-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 +// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-installations-for-a-user func (s *AppsService) ListUserInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) { u, err := addOptions("user/installations", opts) if err != nil { @@ -235,7 +235,7 @@ func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64, opt // CreateAttachment creates a new attachment on user comment containing a url. // -// GitHub API docs: https://developer.github.com/v3/apps/#create-a-content-attachment +// 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)} diff --git a/github/apps_installation.go b/github/apps_installation.go index 59a90c15a99..2f7664cfbac 100644 --- a/github/apps_installation.go +++ b/github/apps_installation.go @@ -90,7 +90,7 @@ func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) ( // 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-repository-from-installation func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64) (*Response, error) { u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID) req, err := s.client.NewRequest("DELETE", u, nil) @@ -104,7 +104,7 @@ func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64 // RevokeInstallationToken revokes an installation token. // -// GitHub docs: https://developer.github.com/v3/apps/installations/#revoke-an-installation-token +// GitHub API docs: https://developer.github.com/v3/apps/installations/#revoke-an-installation-token func (s *AppsService) RevokeInstallationToken(ctx context.Context) (*Response, error) { u := "installation/token" req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/github/apps_marketplace.go b/github/apps_marketplace.go index 053d451dc60..1c8ba2ffd06 100644 --- a/github/apps_marketplace.go +++ b/github/apps_marketplace.go @@ -150,7 +150,7 @@ func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, acc // 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-stubbedticated-user func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opts *ListOptions) ([]*MarketplacePurchase, *Response, error) { uri := "user/marketplace_purchases" if s.Stubbed { diff --git a/github/checks.go b/github/checks.go index 67b7e770217..8d08cb39fbc 100644 --- a/github/checks.go +++ b/github/checks.go @@ -96,7 +96,7 @@ func (c CheckSuite) String() string { // 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) { u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID) req, err := s.client.NewRequest("GET", u, nil) @@ -117,7 +117,7 @@ func (s *ChecksService) GetCheckRun(ctx context.Context, owner, repo string, che // 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) { u := fmt.Sprintf("repos/%v/%v/check-suites/%v", owner, repo, checkSuiteID) req, err := s.client.NewRequest("GET", u, nil) @@ -214,7 +214,7 @@ func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, // 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, opts *ListOptions) ([]*CheckRunAnnotation, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-runs/%v/annotations", owner, repo, checkRunID) u, err := addOptions(u, opts) @@ -255,7 +255,7 @@ type ListCheckRunsResults struct { // 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, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/check-runs", owner, repo, refURLEscape(ref)) u, err := addOptions(u, opts) @@ -321,7 +321,7 @@ type ListCheckSuiteResults struct { // 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, opts *ListCheckSuiteOptions) (*ListCheckSuiteResults, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/check-suites", owner, repo, refURLEscape(ref)) u, err := addOptions(u, opts) @@ -369,7 +369,7 @@ type PreferenceList struct { // 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, opts CheckSuitePreferenceOptions) (*CheckSuitePreferenceResults, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-suites/preferences", owner, repo) req, err := s.client.NewRequest("PATCH", u, opts) @@ -417,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. // -// 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) { u := fmt.Sprintf("repos/%v/%v/check-suites/%v/rerequest", owner, repo, checkSuiteID) diff --git a/github/gen-doc-urls.go b/github/gen-doc-urls.go new file mode 100644 index 00000000000..767d9b0ffbd --- /dev/null +++ b/github/gen-doc-urls.go @@ -0,0 +1,823 @@ +// -*- compile-command: "go run gen-doc-urls.go -v"; -*- +// DO NOT COMMIT WITH COMPILE-COMMAND. + +// 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. + +// +build ignore + +// gen-doc-urls generates GitHub URL docs for each service endpoint. +// +// It is meant to be used by go-github contributors in conjunction with the +// go generate tool before sending a PR to GitHub. +// Please see the CONTRIBUTING.md file for more information. +package main + +import ( + "flag" + "fmt" + "go/ast" + "go/parser" + "go/token" + "io/ioutil" + "log" + "net/http" + "os" + "regexp" + "sort" + "strings" +) + +const ( + skipPrefix = "gen-" + + enterpriseURL = "developer.github.com/enterprise" + stdURL = "developer.github.com" + + enterpriseRefFmt = "// GitHub Enterprise API docs: %v" + stdRefFmt = "// GitHub API docs: %v" +) + +var ( + verbose = flag.Bool("v", false, "Print verbose log messages") + + // methodBlacklist holds methods that do not have GitHub v3 API URLs. + methodBlacklist = map[string]bool{ + "MarketplaceService.marketplaceURI": true, + "RepositoriesService.DownloadContents": true, + "SearchService.search": true, + "UsersService.GetByID": true, + } + + helperOverrides = map[string]overrideFunc{ + "s.search": func(arg string) (httpMethod, url string) { + return "GET", fmt.Sprintf("search/%v", arg) + }, + } + + // methodOverrides contains overrides for troublesome endpoints. + methodOverrides = map[string]string{ + "OrganizationsService.EditOrgMembership: method orgs/%v/memberships/%v": "PUT", + "OrganizationsService.EditOrgMembership: method user/memberships/orgs/%v": "PATCH", + } + + paramRE = regexp.MustCompile(`:[a-z_]+`) +) + +type overrideFunc func(arg string) (httpMethod, url string) + +func logf(fmt string, args ...interface{}) { + if *verbose { + log.Printf(fmt, args...) + } +} + +type servicesMap map[string]*Service +type endpointsMap map[string]*Endpoint + +func main() { + flag.Parse() + fset := token.NewFileSet() + + sourceFilter := func(fi os.FileInfo) bool { + return !strings.HasSuffix(fi.Name(), "_test.go") && !strings.HasPrefix(fi.Name(), skipPrefix) + } + + pkgs, err := parser.ParseDir(fset, ".", sourceFilter, parser.ParseComments) + if err != nil { + log.Fatal(err) + return + } + + // Step 1 - get a map of all services. + services := servicesMap{} + for _, pkg := range pkgs { + for filename, f := range pkg.Files { + if filename != "github.go" { + continue + } + + logf("Step 1 - Processing %v ...", filename) + if err := findClientServices(filename, f, services); err != nil { + log.Fatal(err) + } + } + } + + // Step 2 - find all the API service endpoints. + endpoints := endpointsMap{} + for _, pkg := range pkgs { + for filename, f := range pkg.Files { + if filename == "github.go" { + continue + } + + if filename != "activity_events.go" { // DEBUGGING ONLY!!! + continue + } + + logf("Step 2 - Processing %v ...", filename) + if err := processAST(filename, f, services, endpoints); err != nil { + log.Fatal(err) + } + } + } + + apiDocs := map[string]map[string][]*Endpoint{} // cached by URL, then mapped by web fragment identifier. + urlByMethodAndPath := map[string]string{} + cacheDocs := func(s string) { + url := getURL(s) + if _, ok := apiDocs[url]; ok { + return + } + + // TODO: Enterprise URLs are currently causing problems - for example: + // GET https://developer.github.com/enterprise/v3/enterprise-admin/users/ + // returns StatusCode=404 + if strings.Contains(url, "enterprise") { + logf("Skipping troublesome Enterprise URL: %v", url) + return + } + + logf("GET %q ...", url) + resp, err := http.Get(url) + check("Unable to get URL: %v: %v", url, err) + if resp.StatusCode != http.StatusOK { + log.Fatalf("url %v - StatusCode=%v", url, resp.StatusCode) + } + + b, err := ioutil.ReadAll(resp.Body) + check("Unable to read body of URL: %v, %v", url, err) + check("Unable to close body of URL: %v, %v", url, resp.Body.Close()) + apiDocs[url] = parseWebPageEndpoints(string(b)) + + // Now reverse-map the methods+paths to URLs. + for fragID, v := range apiDocs[url] { + for _, endpoint := range v { + for _, path := range endpoint.urlFormats { + methodAndPath := fmt.Sprintf("%v %v", endpoint.httpMethod, path) + urlByMethodAndPath[methodAndPath] = fmt.Sprintf("%v#%v", url, fragID) + logf("urlByMethodAndPath[%q] = %q", methodAndPath, urlByMethodAndPath[methodAndPath]) + } + } + } + } + + // Step 3 - resolve all missing httpMethods from helperMethods. + // Additionally, use existing URLs as hints to pre-cache all apiDocs. + usedHelpers := map[string]bool{} + endpointsByFilename := map[string][]*Endpoint{} + for k, v := range endpoints { + if _, ok := endpointsByFilename[v.filename]; !ok { + endpointsByFilename[v.filename] = []*Endpoint{} + } + endpointsByFilename[v.filename] = append(endpointsByFilename[v.filename], v) + + for _, cmt := range v.enterpriseRefLines { + cacheDocs(cmt.Text) + } + for _, cmt := range v.stdRefLines { + cacheDocs(cmt.Text) + } + + if v.httpMethod == "" && v.helperMethod != "" { + fullName := fmt.Sprintf("%v.%v", v.serviceName, v.helperMethod) + hm, ok := endpoints[fullName] + if !ok { + log.Fatalf("Unable to find helper method %q for %q", fullName, k) + } + if hm.httpMethod == "" { + log.Fatalf("Helper method %q for %q has empty httpMethod: %#v", fullName, k, hm) + } + v.httpMethod = hm.httpMethod + usedHelpers[fullName] = true + } + } + + // Step 4 - validate and rewrite all URLs, skipping used helper methods. + for filename, slc := range endpointsByFilename { + logf("Step 4 - Processing %v methods in %v ...", len(slc), filename) + + var fileEdits []*FileEdit + for _, endpoint := range slc { + fullName := fmt.Sprintf("%v.%v", endpoint.serviceName, endpoint.endpointName) + if usedHelpers[fullName] { + logf("Step 4 - skipping used helper method %q", fullName) + continue + } + + // First, find the correct GitHub v3 API URL by httpMethod and urlFormat. + for _, path := range endpoint.urlFormats { + path = strings.ReplaceAll(path, "%d", "%v") + path = strings.ReplaceAll(path, "%s", "%v") + methodAndPath := fmt.Sprintf("%v %v", endpoint.httpMethod, path) + url, ok := urlByMethodAndPath[methodAndPath] + if !ok { + log.Printf("WARNING: Unable to find documentation for %v - %q: (%v)", filename, fullName, methodAndPath) + continue + } + logf("found %q for: %q (%v)", url, fullName, methodAndPath) + + // Make sure URL is up-to-date. + switch { + case len(endpoint.enterpriseRefLines) > 1: + log.Printf("WARNING: multiple Enterprise GitHub URLs found - skipping: %#v", endpoint.enterpriseRefLines) + case len(endpoint.enterpriseRefLines) > 0: + line := fmt.Sprintf(enterpriseRefFmt, url) + cmt := endpoint.enterpriseRefLines[0] + if cmt.Text != line { + log.Printf("At token.pos=%v:\nFOUND %q\nWANT: %q", cmt.Pos(), cmt.Text, line) + fileEdits = append(fileEdits, &FileEdit{ + pos: fset.Position(cmt.Pos()), + fromText: cmt.Text, + toText: line, + }) + } + case len(endpoint.stdRefLines) > 1: + log.Printf("WARNING: multiple GitHub URLs found - skipping: %#v", endpoint.stdRefLines) + case len(endpoint.stdRefLines) > 0: + line := fmt.Sprintf(stdRefFmt, url) + cmt := endpoint.stdRefLines[0] + if cmt.Text != line { + log.Printf("At token.pos=%v:\nFOUND %q\nWANT: %q", cmt.Pos(), cmt.Text, line) + fileEdits = append(fileEdits, &FileEdit{ + pos: fset.Position(cmt.Pos()), + fromText: cmt.Text, + toText: line, + }) + } + default: // Missing documentation - add it. + log.Printf("TODO: Add missing documentation: %q for: %q (%v)", url, fullName, methodAndPath) + } + } + } + + if len(fileEdits) > 0 { + logf("Performing %v edits on file %v", len(fileEdits), filename) + // Sort edits from last to first in the file. + sort.Slice(fileEdits, func(a, b int) bool { return fileEdits[b].pos.Offset < fileEdits[a].pos.Offset }) + + b, err := ioutil.ReadFile(filename) + if err != nil { + log.Fatalf("ReadFile: %v", err) + } + + var lastOffset int + for _, edit := range fileEdits { + if edit.pos.Offset == lastOffset { + logf("TODO: At offset %v, inserting second URL of %v bytes", edit.pos.Offset, len(edit.fromText), len(edit.toText)) + continue + } + lastOffset = edit.pos.Offset + logf("At offset %v, replacing %v bytes with %v bytes", edit.pos.Offset, len(edit.fromText), len(edit.toText)) + before := b[0:edit.pos.Offset] + after := b[edit.pos.Offset+len(edit.fromText):] + b = []byte(fmt.Sprintf("%s%v%s", before, edit.toText, after)) + } + + if err := ioutil.WriteFile(filename, b, 0644); err != nil { + log.Fatalf("WriteFile: %v", err) + } + } + } + + logf("Done.") +} + +// FileEdit represents an edit that needs to be performed on a file. +type FileEdit struct { + pos token.Position + fromText string + toText string +} + +func getURL(s string) string { + i := strings.Index(s, "http") + if i < 0 { + return "" + } + j := strings.Index(s, "#") + if j < i { + return s[i:] + } + return s[i:j] +} + +// Service represents a go-github service. +type Service struct { + serviceName string +} + +// Endpoint represents an API endpoint in this repo. +type Endpoint struct { + endpointName string + filename string + serviceName string + urlFormats []string + httpMethod string + helperMethod string // If populated, httpMethod lives in helperMethod. + + enterpriseRefLines []*ast.Comment + stdRefLines []*ast.Comment +} + +func processAST(filename string, f *ast.File, services servicesMap, endpoints endpointsMap) error { + for _, decl := range f.Decls { + switch decl := decl.(type) { + case *ast.FuncDecl: // Doc, Recv, Name, Type, Body + if decl.Recv == nil || len(decl.Recv.List) != 1 || decl.Name == nil || decl.Body == nil { + continue + } + recv := decl.Recv.List[0] + se, ok := recv.Type.(*ast.StarExpr) // Star, X + if !ok || se.X == nil || len(recv.Names) != 1 { + continue + } + recvType, ok := se.X.(*ast.Ident) // NamePos, Name, Obj + if !ok { + return fmt.Errorf("unhandled se.X = %T", se.X) + } + serviceName := recvType.Name + if _, ok := services[serviceName]; !ok { + continue + } + endpointName := decl.Name.Name + fullName := fmt.Sprintf("%v.%v", serviceName, endpointName) + if methodBlacklist[fullName] { + logf("skipping %v", fullName) + continue + } + + receiverName := recv.Names[0].Name + + logf("ast.FuncDecl: %#v", *decl) // Doc, Recv, Name, Type, Body + logf("ast.FuncDecl.Name: %#v", *decl.Name) // NamePos, Name, Obj(nil) + // logf("ast.FuncDecl.Recv: %#v", *decl.Recv) // Opening, List, Closing + logf("ast.FuncDecl.Recv.List[0]: %#v", *recv) // Doc, Names, Type, Tag, Comment + // for i, name := range decl.Recv.List[0].Names { + // logf("recv.name[%v] = %v", i, name.Name) + // } + logf("recvType = %#v", recvType) + var enterpriseRefLines []*ast.Comment + var stdRefLines []*ast.Comment + if decl.Doc != nil { + for i, comment := range decl.Doc.List { + logf("doc.comment[%v] = %#v", i, *comment) + if strings.Contains(comment.Text, enterpriseURL) { + enterpriseRefLines = append(enterpriseRefLines, comment) + } else if strings.Contains(comment.Text, stdURL) { + stdRefLines = append(stdRefLines, comment) + } + } + logf("%v comment lines, %v enterprise URLs, %v standard URLs", len(decl.Doc.List), len(enterpriseRefLines), len(stdRefLines)) + } + + bd := &bodyData{receiverName: receiverName} + if err := bd.parseBody(decl.Body); err != nil { // Lbrace, List, Rbrace + return fmt.Errorf("parseBody: %v", err) + } + + if len(bd.urlFormats) == 1 { + lookupOverride := fmt.Sprintf("%v.%v: %v %v", serviceName, endpointName, bd.httpMethod, bd.urlFormats[0]) + if v, ok := methodOverrides[lookupOverride]; ok { + logf("overriding method for %v to %q", lookupOverride, v) + bd.httpMethod = v + } + } + + ep := &Endpoint{ + endpointName: endpointName, + filename: filename, + serviceName: serviceName, + urlFormats: bd.urlFormats, + httpMethod: bd.httpMethod, + helperMethod: bd.helperMethod, + enterpriseRefLines: enterpriseRefLines, + stdRefLines: stdRefLines, + } + endpoints[fullName] = ep + logf("endpoints[%q] = %#v", fullName, endpoints[fullName]) + if ep.httpMethod == "" && (ep.helperMethod == "" || len(ep.urlFormats) == 0) { + return fmt.Errorf("could not find body info: %#v", *ep) + } + case *ast.GenDecl: + default: + return fmt.Errorf("unhandled decl type: %T", decl) + } + } + + // for _, comment := range f.Comments { + // log.Printf("Found %v comments, starting with: %#v", len(comment.List), comment.List[0]) + // } + + return nil +} + +// bodyData contains information found in a BlockStmt. +type bodyData struct { + receiverName string // receiver name of method to help identify helper methods. + httpMethod string + urlVarName string + urlFormats []string + assignments []lhsrhs + helperMethod string // If populated, httpMethod lives in helperMethod. +} + +func (b *bodyData) parseBody(body *ast.BlockStmt) error { + logf("body=%#v", *body) + + // Find the variable used for the format string, its one-or-more values, + // and the httpMethod used for the NewRequest. + for _, stmt := range body.List { + switch stmt := stmt.(type) { + case *ast.AssignStmt: + hm, uvn, hlp, asgn := processAssignStmt(b.receiverName, stmt) + if b.httpMethod != "" && hm != "" && b.httpMethod != hm { + return fmt.Errorf("found two httpMethod values: %q and %q", b.httpMethod, hm) + } + if hm != "" { + b.httpMethod = hm + // logf("parseBody: httpMethod=%v", b.httpMethod) + } + if hlp != "" { + b.helperMethod = hlp + } + b.assignments = append(b.assignments, asgn...) + // logf("assignments=%#v", b.assignments) + if b.urlVarName == "" && uvn != "" { + b.urlVarName = uvn + // logf("parseBody: urlVarName=%v", b.urlVarName) + // By the time the urlVarName is found, all assignments should + // have already taken place so that we can find the correct + // ones and determine the urlFormats. + for _, lr := range b.assignments { + if lr.lhs == b.urlVarName { + b.urlFormats = append(b.urlFormats, lr.rhs) + logf("found urlFormat: %v", lr.rhs) + } + } + } + case *ast.DeclStmt: + logf("*ast.DeclStmt: %#v", *stmt) + case *ast.DeferStmt: + logf("*ast.DeferStmt: %#v", *stmt) + case *ast.ExprStmt: + logf("*ast.ExprStmt: %#v", *stmt) + case *ast.IfStmt: + if err := b.parseIf(stmt); err != nil { + return err + } + case *ast.RangeStmt: + logf("*ast.RangeStmt: %#v", *stmt) + case *ast.ReturnStmt: // Return Results + logf("*ast.ReturnStmt: %#v", *stmt) + if len(stmt.Results) > 0 { + ce, ok := stmt.Results[0].(*ast.CallExpr) + if ok { + recv, funcName, args := processCallExpr(ce) + logf("return CallExpr: recv=%q, funcName=%q, args=%#v", recv, funcName, args) + // If the httpMethod has not been found at this point, but + // this method is calling a helper function, then see if + // any of its arguments match a previous assignment, then + // record the urlFormat and remember the helper method. + if b.httpMethod == "" && len(args) > 1 && recv == b.receiverName { + if args[0] != "ctx" { + return fmt.Errorf("expected helper function to get ctx as first arg: %#v, %#v", args, *b) + } + if len(b.assignments) == 0 && len(b.urlFormats) == 0 { + b.urlFormats = append(b.urlFormats, strings.Trim(args[1], `"`)) + b.helperMethod = funcName + logf("found urlFormat: %v and helper method: %v", b.urlFormats[0], b.helperMethod) + } else { + for _, lr := range b.assignments { + if lr.lhs == args[1] { // Multiple matches are possible. Loop over all assignments. + b.urlVarName = args[1] + b.urlFormats = append(b.urlFormats, lr.rhs) + b.helperMethod = funcName + logf("found urlFormat: %v and helper method: %v", lr.rhs, b.helperMethod) + } + } + } + } + } + } + case *ast.SwitchStmt: + logf("*ast.SwitchStmt: %#v", *stmt) + default: + return fmt.Errorf("unhandled stmt type: %T", stmt) + } + } + logf("parseBody: assignments=%#v", b.assignments) + + return nil +} + +func (b *bodyData) parseIf(stmt *ast.IfStmt) error { + logf("*ast.IfStmt: %#v", *stmt) + if err := b.parseBody(stmt.Body); err != nil { + return err + } + logf("if body: b=%#v", *b) + if stmt.Else != nil { + switch els := stmt.Else.(type) { + case *ast.BlockStmt: + if err := b.parseBody(els); err != nil { + return err + } + logf("if else: b=%#v", *b) + case *ast.IfStmt: + if err := b.parseIf(els); err != nil { + return err + } + default: + return fmt.Errorf("unhandled else stmt type %T", els) + } + } + + return nil +} + +// lhsrhs represents an assignment with a variable name on the left +// and a string on the right - used to find the URL format string. +type lhsrhs struct { + lhs string + rhs string +} + +func processAssignStmt(receiverName string, stmt *ast.AssignStmt) (httpMethod, urlVarName, helperMethod string, assignments []lhsrhs) { + logf("*ast.AssignStmt: %#v", *stmt) // Lhs, TokPos, Tok, Rhs + var lhs []string + for _, expr := range stmt.Lhs { + switch expr := expr.(type) { + case *ast.Ident: // NamePos, Name, Obj + logf("processAssignStmt: *ast.Ident: %#v", expr) + lhs = append(lhs, expr.Name) + case *ast.SelectorExpr: // X, Sel + logf("processAssignStmt: *ast.SelectorExpr: %#v", expr) + default: + log.Fatalf("unhandled AssignStmt Lhs type: %T", expr) + } + } + + for i, expr := range stmt.Rhs { + switch expr := expr.(type) { + case *ast.BasicLit: // ValuePos, Kind, Value + assignments = append(assignments, lhsrhs{lhs: lhs[i], rhs: strings.Trim(expr.Value, `"`)}) + case *ast.BinaryExpr: + logf("processAssignStmt: *ast.BinaryExpr: %#v", *expr) + case *ast.CallExpr: // Fun, Lparen, Args, Ellipsis, Rparen + recv, funcName, args := processCallExpr(expr) + logf("processAssignStmt: CallExpr: recv=%q, funcName=%q, args=%#v", recv, funcName, args) + switch funcName { + case "addOptions": + if v := strings.Trim(args[0], `"`); v != args[0] { + assignments = append(assignments, lhsrhs{lhs: lhs[i], rhs: v}) + urlVarName = lhs[i] + } else { + urlVarName = args[0] + } + case "Sprintf": + assignments = append(assignments, lhsrhs{lhs: lhs[i], rhs: strings.Trim(args[0], `"`)}) + case "NewRequest": + httpMethod = strings.Trim(args[0], `"`) + urlVarName = args[1] + case "NewUploadRequest": + httpMethod = "POST" + urlVarName = args[0] + } + if recv == receiverName && len(args) > 1 && args[0] == "ctx" { // This might be a helper method. + fullName := fmt.Sprintf("%v.%v", recv, funcName) + logf("checking for override: fullName=%v", fullName) + if fn, ok := helperOverrides[fullName]; ok { + logf("found helperOverride for %v", fullName) + hm, url := fn(strings.Trim(args[1], `"`)) + httpMethod = hm + urlVarName = "u" // arbitrary + assignments = []lhsrhs{{lhs: urlVarName, rhs: url}} + } else { + urlVarName = args[1] // For this to work correctly, the URL must be the second arg to the helper method! + helperMethod = funcName + logf("found possible helper method: funcName=%v, urlVarName=%v", funcName, urlVarName) + } + } + case *ast.CompositeLit: // Type, Lbrace, Elts, Rbrace, Incomplete + logf("processAssignStmt: *ast.CompositeLit: %#v", *expr) + case *ast.FuncLit: + logf("processAssignStmt: *ast.FuncLit: %#v", *expr) + case *ast.SelectorExpr: + logf("processAssignStmt: *ast.SelectorExpr: %#v", *expr) + case *ast.UnaryExpr: // OpPos, Op, X + logf("processAssignStmt: *ast.UnaryExpr: %#v", *expr) + default: + log.Fatalf("unhandled AssignStmt Rhs type: %T", expr) + } + } + logf("urlVarName=%v, assignments=%#v", urlVarName, assignments) + + return httpMethod, urlVarName, helperMethod, assignments +} + +func processCallExpr(expr *ast.CallExpr) (recv, funcName string, args []string) { + logf("*ast.CallExpr: %#v", *expr) + + for _, arg := range expr.Args { + switch arg := arg.(type) { + case *ast.ArrayType: + logf("processCallExpr: *ast.ArrayType: %#v", arg) + case *ast.BasicLit: // ValuePos, Kind, Value + args = append(args, arg.Value) // Do not trim quotes here so as to identify it later as a string literal. + case *ast.CallExpr: // Fun, Lparen, Args, Ellipsis, Rparen + logf("processCallExpr: *ast.CallExpr: %#v", arg) + r, fn, as := processCallExpr(arg) + if r == "fmt" && fn == "Sprintf" && len(as) > 0 { // Special case - return format string. + args = append(args, as[0]) + } + case *ast.Ident: // NamePos, Name, Obj + args = append(args, arg.Name) + case *ast.MapType: + logf("processCallExpr: *ast.MapType: %#v", arg) + case *ast.SelectorExpr: // X, Sel + logf("processCallExpr: *ast.SelectorExpr: %#v", arg) + x, ok := arg.X.(*ast.Ident) + if ok { // special case + switch name := fmt.Sprintf("%v.%v", x.Name, arg.Sel.Name); name { + case "http.MethodGet": + args = append(args, http.MethodGet) + case "http.MethodHead": + args = append(args, http.MethodHead) + case "http.MethodPost": + args = append(args, http.MethodPost) + case "http.MethodPut": + args = append(args, http.MethodPut) + case "http.MethodPatch": + args = append(args, http.MethodPatch) + case "http.MethodDelete": + args = append(args, http.MethodDelete) + case "http.MethodConnect": + args = append(args, http.MethodConnect) + case "http.MethodOptions": + args = append(args, http.MethodOptions) + case "http.MethodTrace": + args = append(args, http.MethodTrace) + default: + args = append(args, name) + } + } + case *ast.StarExpr: + logf("processCallExpr: *ast.StarExpr: %#v", arg) + case *ast.StructType: + logf("processCallExpr: *ast.StructType: %#v", arg) + case *ast.UnaryExpr: // OpPos, Op, X + switch x := arg.X.(type) { + case *ast.Ident: + args = append(args, x.Name) + case *ast.CompositeLit: // Type, Lbrace, Elts, Rbrace, Incomplete + logf("processCallExpr: *ast.CompositeLit: %#v", x) + default: + log.Fatalf("processCallExpr: unhandled UnaryExpr.X arg type: %T", arg.X) + } + default: + log.Fatalf("processCallExpr: unhandled arg type: %T", arg) + } + } + + switch fun := expr.Fun.(type) { + case *ast.Ident: // NamePos, Name, Obj + funcName = fun.Name + case *ast.SelectorExpr: // X, Sel + funcName = fun.Sel.Name + switch x := fun.X.(type) { + case *ast.Ident: // NamePos, Name, Obj + logf("processCallExpr: X recv *ast.Ident=%#v", x) + recv = x.Name + case *ast.ParenExpr: + logf("processCallExpr: X recv *ast.ParenExpr: %#v", x) + case *ast.SelectorExpr: // X, Sel + logf("processCallExpr: X recv *ast.SelectorExpr: %#v", x.Sel) + recv = x.Sel.Name + default: + log.Fatalf("processCallExpr: unhandled X receiver type: %T", x) + } + default: + log.Fatalf("processCallExpr: unhandled Fun: %T", expr.Fun) + } + + return recv, funcName, args +} + +// findClientServices finds all go-github services from the Client struct. +func findClientServices(filename string, f *ast.File, services servicesMap) error { + for _, decl := range f.Decls { + switch decl := decl.(type) { + case *ast.GenDecl: + if decl.Tok != token.TYPE || len(decl.Specs) != 1 { + continue + } + ts, ok := decl.Specs[0].(*ast.TypeSpec) + if !ok || decl.Doc == nil || ts.Name == nil || ts.Type == nil || ts.Name.Name != "Client" { + continue + } + st, ok := ts.Type.(*ast.StructType) + if !ok || st.Fields == nil || len(st.Fields.List) == 0 { + continue + } + + for _, field := range st.Fields.List { + se, ok := field.Type.(*ast.StarExpr) + if !ok || se.X == nil || len(field.Names) != 1 { + continue + } + id, ok := se.X.(*ast.Ident) + if !ok { + continue + } + name := id.Name + if !strings.HasSuffix(name, "Service") { + continue + } + + services[name] = &Service{serviceName: name} + } + + return nil // Found all services in Client struct. + } + } + + return fmt.Errorf("unable to find Client struct in github.go") +} + +func check(fmtStr string, args ...interface{}) { + if err := args[len(args)-1]; err != nil { + log.Fatalf(fmtStr, args...) + } +} + +// parseWebPageEndpoints returns endpoint information, mapped by +// web page fragment identifier. +func parseWebPageEndpoints(buf string) map[string][]*Endpoint { + result := map[string][]*Endpoint{} + + // The GitHub v3 API web pages do not appear to be auto-generated + // and therefore, the XML decoder is too strict to reliably parse them. + // Here is a tiny example where the XML decoder completely fails + // due to mal-formed HTML: + // + // + // + // ... + // + + parts := strings.Split(buf, "") + var lastFragmentID string + for _, part := range parts { + for _, method := range httpMethods { + if strings.HasPrefix(part, method) { + eol := strings.Index(part, "\n") + if eol < 0 { + eol = len(part) + } + if v := strings.Index(part, "<"); v > len(method) && v < eol { + eol = v + } + path := strings.TrimSpace(part[len(method):eol]) + path = paramRE.ReplaceAllString(path, "%v") + // strip leading garbage + if i := strings.Index(path, "/"); i >= 0 { + path = path[i+1:] + } + path = strings.TrimSuffix(path, ".") + logf("Found %v %v", method, path) + result[lastFragmentID] = append(result[lastFragmentID], &Endpoint{ + urlFormats: []string{path}, + httpMethod: method, + }) + } + } + + if i := strings.LastIndex(part, "= 0 { + lastFragmentID = b[:i] + logf("Found lastFragmentID: %v", lastFragmentID) + } + } + } + + return result +} + +var httpMethods = []string{ + "GET", + "HEAD", + "POST", + "PUT", + "PATCH", + "DELETE", + "CONNECT", + "OPTIONS", + "TRACE", +} diff --git a/github/gen-doc-urls_test.go b/github/gen-doc-urls_test.go new file mode 100644 index 00000000000..10d29a19a3a --- /dev/null +++ b/github/gen-doc-urls_test.go @@ -0,0 +1,3143 @@ +// -*- compile-command: "go test -v gen-doc-urls*.go"; -*- +// +build ignore + +package main + +import ( + "reflect" + "testing" +) + +func TestParseWebPageEndpoints(t *testing.T) { + got := parseWebPageEndpoints(testPage) + + for k := range got { + w, ok := want[k] + if !ok { + t.Errorf("got[%q] =\n%#v\nwant[%q] = nil", k, got[k], k) + continue + } + if len(got[k]) != len(w) { + t.Errorf("len(got[%q]) = %v, len(want[%q]) = %v", k, len(got[k]), k, len(w)) + continue + } + for i := 0; i < len(w); i++ { + if !reflect.DeepEqual(got[k][i], w[i]) { + t.Errorf("got[%q][%v] =\n%#v\nwant[%q][%v]:\n%#v", k, i, got[k][i], k, i, want[k][i]) + } + } + } + for k := range want { + if _, ok := got[k]; !ok { + t.Errorf("got[%q] = nil\nwant[%q]:\n%#v", k, k, want[k]) + } + } +} + +var want = map[string][]*Endpoint{ + "list-reactions-for-a-commit-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/comments/%v/reactions"}, httpMethod: "GET"}}, + + "delete-a-commit-comment-reaction": []*Endpoint{ + {urlFormats: []string{"repositories/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"repos/%v/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "create-reaction-for-an-issue": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/%v/reactions"}, httpMethod: "POST"}}, + + "delete-an-issue-reaction": []*Endpoint{ + {urlFormats: []string{"repositories/%v/issues/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"repos/%v/%v/issues/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "create-reaction-for-a-pull-request-review-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/pulls/comments/%v/reactions"}, httpMethod: "POST"}}, + + "list-reactions-for-a-team-discussion": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/reactions"}, httpMethod: "GET"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/reactions"}, httpMethod: "GET"}, + }, + + "delete-a-reaction-legacy": []*Endpoint{{urlFormats: []string{"reactions/%v"}, httpMethod: "DELETE"}}, + + "list-reactions-for-a-team-discussion-comment-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "GET"}}, + + "delete-an-issue-comment-reaction": []*Endpoint{ + {urlFormats: []string{"repositories/%v/issues/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"repos/%v/%v/issues/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "list-reactions-for-a-pull-request-review-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/pulls/comments/%v/reactions"}, httpMethod: "GET"}}, + + "create-reaction-for-a-team-discussion-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/reactions"}, httpMethod: "POST"}}, + + "create-reaction-for-a-team-discussion-comment-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "POST"}}, + + "create-reaction-for-a-commit-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/comments/%v/reactions"}, httpMethod: "POST"}}, + + "list-reactions-for-an-issue": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/%v/reactions"}, httpMethod: "GET"}}, + + "create-reaction-for-an-issue-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/comments/%v/reactions"}, httpMethod: "POST"}}, + + "create-reaction-for-a-team-discussion": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/reactions"}, httpMethod: "POST"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/reactions"}, httpMethod: "POST"}, + }, + + "delete-team-discussion-reaction": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "create-reaction-for-a-team-discussion-comment": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "POST"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "POST"}, + }, + + "list-reactions-for-an-issue-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/comments/%v/reactions"}, httpMethod: "GET"}}, + + "delete-a-pull-request-comment-reaction": []*Endpoint{ + {urlFormats: []string{"repositories/%v/pulls/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"repos/%v/%v/pulls/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "list-reactions-for-a-team-discussion-comment": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "GET"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "GET"}, + }, + + "delete-team-discussion-comment-reaction": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "list-reactions-for-a-team-discussion-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/reactions"}, httpMethod: "GET"}}, +} + +var testPage = ` + + + + + + + + + Reactions | GitHub Developer Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+

+ Reactions

+ + + +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

+ Reaction types

+ +

When creating a reaction, the allowed values for the content parameter are as follows (with the + corresponding emoji for reference):

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
contentemoji
+1:+1:
-1:-1:
laugh:smile:
confused:confused:
heart:heart:
hooray:tada:
rocket:rocket:
eyes:eyes:
+ +

+ List reactions for a + commit comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a commit comment.

+ +
GET /repos/:owner/:repo/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a commit comment.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a + commit comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a commit comment. A response with a + Status: 200 OK means that you already added the reaction type to this commit comment.

+ +
POST /repos/:owner/:repo/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + commit comment.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete a commit comment + reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a repository by repository_id using the route + DELETE /repositories/:repository_id/comments/:comment_id/reactions/:reaction_id.

+ +
+ +

Delete a reaction to a commit comment.

+ +
DELETE /repos/:owner/:repo/comments/:comment_id/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for an + issue +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to an issue.

+ +
GET /repos/:owner/:repo/issues/:issue_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to an issue.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for an + issue

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to an issue. A response with a Status: 200 OK means + that you already added the reaction type to this issue.

+ +
POST /repos/:owner/:repo/issues/:issue_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + issue.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete an issue reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a repository by repository_id using the route + DELETE /repositories/:repository_id/issues/:issue_number/reactions/:reaction_id.

+ +
+ +

Delete a reaction to an issue.

+ +
DELETE /repos/:owner/:repo/issues/:issue_number/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for an + issue comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to an issue comment.

+ +
GET /repos/:owner/:repo/issues/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to an issue comment.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for an + issue comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to an issue comment. A response with a + Status: 200 OK means that you already added the reaction type to this issue comment.

+ +
POST /repos/:owner/:repo/issues/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + issue comment.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete an issue comment + reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a repository by repository_id using the route + DELETE delete /repositories/:repository_id/issues/comments/:comment_id/reactions/:reaction_id. +

+ +
+ +

Delete a reaction to an issue comment.

+ +
DELETE /repos/:owner/:repo/issues/comments/:comment_id/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for a pull request review comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a pull request review comment.

+ +
GET /repos/:owner/:repo/pulls/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a pull request review comment.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a pull request review comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a pull request review comment. A response with a + Status: 200 OK means that you already added the reaction type to this pull request review + comment.

+ +
POST /repos/:owner/:repo/pulls/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + pull request review comment.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete a pull request + comment reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a repository by repository_id using the route + DELETE /repositories/:repository_id/pulls/comments/:comment_id/reactions/:reaction_id.

+ +
+ +

Delete a reaction to a pull request review comment.

+ +
DELETE /repos/:owner/:repo/pulls/comments/:comment_id/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for a + team discussion +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a team discussion. OAuth access tokens require the + read:discussion scope.

+ +
+ +

Note: You can also specify a team by org_id and team_id using + the route GET /organizations/:org_id/team/:team_id/discussions/:discussion_number/reactions. +

+ +
+ +
GET /orgs/:org/teams/:team_slug/discussions/:discussion_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a team discussion.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a + team discussion

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a team discussion. OAuth access tokens require the + write:discussion scope. A response with a + Status: 200 OK means that you already added the reaction type to this team discussion.

+ +
+ +

Note: You can also specify a team by org_id and team_id using + the route POST /organizations/:org_id/team/:team_id/discussions/:discussion_number/reactions. +

+ +
+ +
POST /orgs/:org/teams/:team_slug/discussions/:discussion_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + team discussion.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete team discussion + reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a team or organization with team_id and + org_id using the route + DELETE /organizations/:org_id/team/:team_id/discussions/:discussion_number/reactions/:reaction_id. +

+ +
+ +

Delete a reaction to a team discussion. OAuth access tokens require the + write:discussion scope.

+ +
DELETE /orgs/:org/teams/:team_slug/discussions/:discussion_number/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for a team discussion comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a team discussion comment. OAuth access + tokens require the read:discussion scope.

+ +
+ +

Note: You can also specify a team by org_id and team_id using + the route + GET /organizations/:org_id/team/:team_id/discussions/:discussion_number/comments/:comment_number/reactions. +

+ +
+ +
GET /orgs/:org/teams/:team_slug/discussions/:discussion_number/comments/:comment_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a team discussion comment.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a team discussion comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a team discussion comment. OAuth access + tokens require the write:discussion scope. A response with a + Status: 200 OK means that you already added the reaction type to this team discussion comment. +

+ +
+ +

Note: You can also specify a team by org_id and team_id using + the route + POST /organizations/:org_id/team/:team_id/discussions/:discussion_number/comments/:comment_number/reactions. +

+ +
+ +
POST /orgs/:org/teams/:team_slug/discussions/:discussion_number/comments/:comment_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + team discussion comment.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete team discussion + comment reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a team or organization with team_id and + org_id using the route + DELETE /organizations/:org_id/team/:team_id/discussions/:discussion_number/comments/:comment_number/reactions/:reaction_id. +

+ +
+ +

Delete a reaction to a team discussion comment. OAuth access + tokens require the write:discussion scope.

+ +
DELETE /orgs/:org/teams/:team_slug/discussions/:discussion_number/comments/:comment_number/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ Delete a reaction (Legacy) +

+ +
+ +

Deprecation Notice: This endpoint route is deprecated and will be removed from the + Reactions API. We recommend migrating your existing code to use the new delete reactions endpoints. For more + information, see this blog post.

+ +
+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

OAuth access tokens require the write:discussion scope, when deleting a team discussion or team + discussion comment.

+ +
DELETE /reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for a team discussion (Legacy) +

+ +
+ +

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams + API. We recommend migrating your existing code to use the new List reactions for a team discussion + endpoint.

+ +
+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a team discussion. OAuth access tokens require the + read:discussion scope.

+ +
GET /teams/:team_id/discussions/:discussion_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a team discussion.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a team discussion (Legacy)

+ +
+ +

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams + API. We recommend migrating your existing code to use the new Create reaction for a team discussion + endpoint.

+ +
+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a team discussion. OAuth access tokens require the + write:discussion scope. A response with a + Status: 200 OK means that you already added the reaction type to this team discussion.

+ +
POST /teams/:team_id/discussions/:discussion_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + team discussion.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ List reactions for a team discussion comment (Legacy) +

+ +
+ +

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams + API. We recommend migrating your existing code to use the new List reactions for a team discussion comment + endpoint.

+ +
+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a team discussion comment. OAuth access + tokens require the read:discussion scope.

+ +
GET /teams/:team_id/discussions/:discussion_number/comments/:comment_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a team discussion comment.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a team discussion comment (Legacy) +

+ +
+ +

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams + API. We recommend migrating your existing code to use the new Create reaction for a team discussion comment + endpoint.

+ +
+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a team discussion comment. OAuth access + tokens require the write:discussion scope. A response with a + Status: 200 OK means that you already added the reaction type to this team discussion comment. +

+ +
POST /teams/:team_id/discussions/:discussion_number/comments/:comment_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + team discussion comment.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ +
+ + + + + +
+
+ + + + + + + + +` diff --git a/github/gists.go b/github/gists.go index 0f326055421..915ee381812 100644 --- a/github/gists.go +++ b/github/gists.go @@ -96,7 +96,7 @@ type GistListOptions struct { // is authenticated, it will returns all gists for the authenticated // user. // -// GitHub API docs: https://developer.github.com/v3/gists/#list-gists +// GitHub API docs: https://developer.github.com/v3/gists/#list-gists-for-the-authenticated-user-for-a-user func (s *GistsService) List(ctx context.Context, user string, opts *GistListOptions) ([]*Gist, *Response, error) { var u string if user != "" { @@ -125,7 +125,7 @@ func (s *GistsService) List(ctx context.Context, user string, opts *GistListOpti // 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, opts *GistListOptions) ([]*Gist, *Response, error) { u, err := addOptions("gists/public", opts) if err != nil { @@ -148,7 +148,7 @@ func (s *GistsService) ListAll(ctx context.Context, opts *GistListOptions) ([]*G // 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, opts *GistListOptions) ([]*Gist, *Response, error) { u, err := addOptions("gists/starred", opts) if err != nil { @@ -171,7 +171,7 @@ func (s *GistsService) ListStarred(ctx context.Context, opts *GistListOptions) ( // 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) { u := fmt.Sprintf("gists/%v", id) req, err := s.client.NewRequest("GET", u, nil) @@ -228,7 +228,7 @@ func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response // 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) { u := fmt.Sprintf("gists/%v", id) req, err := s.client.NewRequest("PATCH", u, gist) diff --git a/github/issues.go b/github/issues.go index bc3b83e732b..8c2f47ea686 100644 --- a/github/issues.go +++ b/github/issues.go @@ -129,7 +129,7 @@ type PullRequestLinks struct { // organization repositories; if false, list only owned and member // repositories. // -// GitHub API docs: https://developer.github.com/v3/issues/#list-issues +// GitHub API docs: https://developer.github.com/v3/issues/#list-user-account-issues-assigned-to-the-authenticated-user-assigned-to-the-authenticated-user func (s *IssuesService) List(ctx context.Context, all bool, opts *IssueListOptions) ([]*Issue, *Response, error) { var u string if all { @@ -143,7 +143,7 @@ func (s *IssuesService) List(ctx context.Context, all bool, opts *IssueListOptio // ListByOrg fetches the issues in the specified organization for the // 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, opts *IssueListOptions) ([]*Issue, *Response, error) { u := fmt.Sprintf("orgs/%v/issues", org) return s.listIssues(ctx, u, opts) @@ -243,7 +243,7 @@ func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo strin // 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) { u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) req, err := s.client.NewRequest("GET", u, nil) @@ -285,7 +285,7 @@ func (s *IssuesService) Create(ctx context.Context, owner string, repo string, i // 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) { u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) req, err := s.client.NewRequest("PATCH", u, issue) diff --git a/github/issues_comments.go b/github/issues_comments.go index 56b24c19179..b56f5d4d649 100644 --- a/github/issues_comments.go +++ b/github/issues_comments.go @@ -50,7 +50,7 @@ type IssueListCommentsOptions struct { // ListComments lists all comments on the specified issue. Specifying an issue // 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-comments-in-a-repository func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opts *IssueListCommentsOptions) ([]*IssueComment, *Response, error) { var u string if number == 0 { diff --git a/github/migrations.go b/github/migrations.go index f4260bb77cc..86b7c2789e0 100644 --- a/github/migrations.go +++ b/github/migrations.go @@ -74,7 +74,7 @@ type startMigration struct { // StartMigration starts the generation of a migration archive. // 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, opts *MigrationOptions) (*Migration, *Response, error) { u := fmt.Sprintf("orgs/%v/migrations", org) @@ -103,7 +103,7 @@ func (s *MigrationService) StartMigration(ctx context.Context, org string, repos // ListMigrations lists the most recent migrations. // -// GitHub API docs: https://developer.github.com/v3/migrations/orgs/#get-a-list-of-organization-migrations +// GitHub API docs: https://developer.github.com/v3/migrations/orgs/#list-organization-migrations func (s *MigrationService) ListMigrations(ctx context.Context, org string, opts *ListOptions) ([]*Migration, *Response, error) { u := fmt.Sprintf("orgs/%v/migrations", org) u, err := addOptions(u, opts) @@ -131,7 +131,7 @@ func (s *MigrationService) ListMigrations(ctx context.Context, org string, opts // MigrationStatus gets the status of a specific migration archive. // 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-the-status-of-an-organization-migration func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) { u := fmt.Sprintf("orgs/%v/migrations/%v", org, id) @@ -155,7 +155,7 @@ func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id i // MigrationArchiveURL fetches a migration archive URL. // 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) { u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) @@ -192,7 +192,7 @@ func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, // DeleteMigration deletes a previous migration archive. // 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) { u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) @@ -212,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 // 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) { u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo) diff --git a/github/migrations_user.go b/github/migrations_user.go index 5b58d293544..5224d7b844c 100644 --- a/github/migrations_user.go +++ b/github/migrations_user.go @@ -96,7 +96,7 @@ func (s *MigrationService) StartUserMigration(ctx context.Context, repos []strin // 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) { u := "user/migrations" diff --git a/github/orgs.go b/github/orgs.go index 3c87ec84d4f..d0631495062 100644 --- a/github/orgs.go +++ b/github/orgs.go @@ -144,7 +144,7 @@ func (s *OrganizationsService) ListAll(ctx context.Context, opts *OrganizationsL // List the organizations for a user. Passing the empty string will list // 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, opts *ListOptions) ([]*Organization, *Response, error) { var u string if user != "" { @@ -214,7 +214,7 @@ func (s *OrganizationsService) GetByID(ctx context.Context, id int64) (*Organiza // 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) { u := fmt.Sprintf("orgs/%v", name) req, err := s.client.NewRequest("PATCH", u, org) diff --git a/github/orgs_members.go b/github/orgs_members.go index 6b96d05f67c..e701be6dbd2 100644 --- a/github/orgs_members.go +++ b/github/orgs_members.go @@ -71,7 +71,7 @@ type ListMembersOptions struct { // user is an owner of the organization, this will return both concealed and // 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/#public-members-list func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opts *ListMembersOptions) ([]*User, *Response, error) { var u string if opts != nil && opts.PublicOnly { @@ -322,7 +322,7 @@ type CreateOrgInvitationOptions struct { // In order to create invitations in an organization, // 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-organization-invitation func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opts *CreateOrgInvitationOptions) (*Invitation, *Response, error) { u := fmt.Sprintf("orgs/%v/invitations", org) diff --git a/github/pulls.go b/github/pulls.go index 00692088647..349c79e6b2b 100644 --- a/github/pulls.go +++ b/github/pulls.go @@ -458,7 +458,7 @@ type pullRequestMergeRequest struct { // Merge a pull request (Merge Button™). // commitMessage is the title for the 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-merge-button 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) diff --git a/github/pulls_comments.go b/github/pulls_comments.go index 88fb209b6fa..230adcc4c72 100644 --- a/github/pulls_comments.go +++ b/github/pulls_comments.go @@ -66,7 +66,7 @@ type PullRequestListCommentsOptions struct { // pull request number of 0 will return all comments on all pull requests for // 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-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 if number == 0 { @@ -144,7 +144,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. // -// GitHub API docs: https://developer.github.com/v3/pulls/comments/#alternative-input +// GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-comment func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner string, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) { comment := &struct { Body string `json:"body,omitempty"` diff --git a/github/reactions.go b/github/reactions.go index 1602032e221..6c72fec52fa 100644 --- a/github/reactions.go +++ b/github/reactions.go @@ -274,7 +274,7 @@ func (s *ReactionsService) DeleteIssueCommentReactionByID(ctx context.Context, r // 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, opts *ListOptions) ([]*Reaction, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) u, err := addOptions(u, opts) @@ -346,7 +346,7 @@ func (s *ReactionsService) DeletePullRequestCommentReactionByID(ctx context.Cont // 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, opts *ListOptions) ([]*Reaction, *Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) u, err := addOptions(u, opts) @@ -373,7 +373,7 @@ func (s *ReactionsService) ListTeamDiscussionReactions(ctx context.Context, team // CreateTeamDiscussionReaction creates a reaction for a team discussion. // 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) { u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) @@ -414,7 +414,7 @@ func (s *ReactionsService) DeleteTeamDiscussionReactionByOrgIDAndTeamID(ctx cont // 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, opts *ListOptions) ([]*Reaction, *Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) u, err := addOptions(u, opts) @@ -440,7 +440,7 @@ func (s *ReactionsService) ListTeamDiscussionCommentReactions(ctx context.Contex // CreateTeamDiscussionCommentReaction creates a reaction for a team discussion comment. // 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) { u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) @@ -479,7 +479,7 @@ func (s *ReactionsService) DeleteTeamDiscussionCommentReactionByOrgIDAndTeamID(c return s.deleteReaction(ctx, url) } -func (s ReactionsService) deleteReaction(ctx context.Context, url string) (*Response, error) { +func (s *ReactionsService) deleteReaction(ctx context.Context, url string) (*Response, error) { req, err := s.client.NewRequest(http.MethodDelete, url, nil) if err != nil { return nil, err diff --git a/github/repos.go b/github/repos.go index 41249226d1a..c7f09d40a91 100644 --- a/github/repos.go +++ b/github/repos.go @@ -182,7 +182,7 @@ type RepositoryListOptions struct { // List the repositories for a user. Passing the empty string will list // 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-the-authenticated-usera-user func (s *RepositoriesService) List(ctx context.Context, user string, opts *RepositoryListOptions) ([]*Repository, *Response, error) { var u string if user != "" { @@ -268,7 +268,7 @@ type RepositoryListAllOptions struct { // 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, opts *RepositoryListAllOptions) ([]*Repository, *Response, error) { u, err := addOptions("repositories", opts) if err != nil { @@ -326,7 +326,7 @@ type createRepoRequest struct { // Note that only a subset of the repo fields are used and repo must // 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-an-organization-repository func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { var u string if org != "" { @@ -383,7 +383,7 @@ type TemplateRepoRequest struct { // CreateFromTemplate generates a repository from a template. // -// GitHub API docs: https://developer.github.com/v3/repos/#create-repository-using-a-repository-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) @@ -404,7 +404,7 @@ func (s *RepositoriesService) CreateFromTemplate(ctx context.Context, templateOw // 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) { u := fmt.Sprintf("repos/%v/%v", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -469,7 +469,7 @@ func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repositor // 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) { u := fmt.Sprintf("repos/%v/%v", owner, repo) req, err := s.client.NewRequest("PATCH", u, repository) @@ -893,7 +893,7 @@ type SignaturesProtectedBranch struct { // 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, opts *BranchListOptions) ([]*Branch, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches", owner, repo) u, err := addOptions(u, opts) @@ -920,7 +920,7 @@ func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, re // 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-branch 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) req, err := s.client.NewRequest("GET", u, nil) @@ -1299,7 +1299,7 @@ type repositoryTopics struct { // 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) { u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -1321,7 +1321,7 @@ func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo str // 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) { u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) t := &repositoryTopics{ diff --git a/github/repos_collaborators.go b/github/repos_collaborators.go index bdfe04f13f3..e461516cae0 100644 --- a/github/repos_collaborators.go +++ b/github/repos_collaborators.go @@ -68,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 // 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-collaborator 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) req, err := s.client.NewRequest("GET", u, nil) @@ -141,7 +141,7 @@ func (s *RepositoriesService) AddCollaborator(ctx context.Context, owner, 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. // -// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#remove-collaborator +// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#remove-user-as-a-collaborator func (s *RepositoriesService) RemoveCollaborator(ctx context.Context, owner, repo, user string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/github/repos_commits.go b/github/repos_commits.go index 77bd748187f..59a2322b6b5 100644 --- a/github/repos_commits.go +++ b/github/repos_commits.go @@ -123,7 +123,7 @@ type BranchCommit struct { // 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-on-a-repository 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, err := addOptions(u, opts) @@ -195,7 +195,7 @@ 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 // 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-single-commit 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, refURLEscape(ref)) diff --git a/github/repos_community_health.go b/github/repos_community_health.go index 73d1d573bff..e8775a6c15e 100644 --- a/github/repos_community_health.go +++ b/github/repos_community_health.go @@ -38,7 +38,7 @@ type CommunityHealthMetrics struct { // 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/#retrieve-community-profile-metrics func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, owner, repo string) (*CommunityHealthMetrics, *Response, error) { u := fmt.Sprintf("repos/%v/%v/community/profile", owner, repo) req, err := s.client.NewRequest("GET", u, nil) diff --git a/github/repos_contents.go b/github/repos_contents.go index ede93e4f4b5..015d9471a5e 100644 --- a/github/repos_contents.go +++ b/github/repos_contents.go @@ -177,7 +177,7 @@ func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path // CreateFile creates a new file in a repository at the given path and returns // 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-a-file 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) req, err := s.client.NewRequest("PUT", u, opts) @@ -195,7 +195,7 @@ func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path // 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. // -// 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-a-file 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) req, err := s.client.NewRequest("PUT", u, opts) diff --git a/github/repos_hooks.go b/github/repos_hooks.go index 5af71dfd11f..d81e74c9cf9 100644 --- a/github/repos_hooks.go +++ b/github/repos_hooks.go @@ -131,7 +131,7 @@ func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string // 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-hooks 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, err := addOptions(u, opts) diff --git a/github/repos_keys.go b/github/repos_keys.go index 64ee7422a07..e389504e660 100644 --- a/github/repos_keys.go +++ b/github/repos_keys.go @@ -14,7 +14,7 @@ import ( // 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, opts *ListOptions) ([]*Key, *Response, error) { u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) u, err := addOptions(u, opts) @@ -38,7 +38,7 @@ func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo s // 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) { 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. // -// GitHub API docs: https://developer.github.com/v3/repos/keys/#create +// GitHub API docs: https://developer.github.com/v3/repos/keys/#add-a-new-deploy-key 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) @@ -98,7 +98,7 @@ func (s *RepositoriesService) EditKey(ctx context.Context, owner string, repo st // 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/#remove-a-deploy-key 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) diff --git a/github/repos_pages.go b/github/repos_pages.go index 58826527d9d..bdbd84b6c04 100644 --- a/github/repos_pages.go +++ b/github/repos_pages.go @@ -165,7 +165,7 @@ func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo s // 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) { u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -184,7 +184,7 @@ func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, re // 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-a-specific-pages-build 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) req, err := s.client.NewRequest("GET", u, nil) diff --git a/github/repos_stats.go b/github/repos_stats.go index e9c6d3fff4d..0e257bad39d 100644 --- a/github/repos_stats.go +++ b/github/repos_stats.go @@ -45,7 +45,7 @@ func (w WeeklyStats) String() string { // 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. // -// GitHub API docs: https://developer.github.com/v3/repos/statistics/#contributors +// GitHub API docs: https://developer.github.com/v3/repos/statistics/#get-contributors-list-with-additions-deletions-and-commit-counts func (s *RepositoriesService) ListContributorsStats(ctx context.Context, owner, repo string) ([]*ContributorStats, *Response, error) { u := fmt.Sprintf("repos/%v/%v/stats/contributors", owner, repo) 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 // 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-data func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, repo string) ([]*WeeklyCommitActivity, *Response, error) { u := fmt.Sprintf("repos/%v/%v/stats/commit_activity", owner, repo) 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 // 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-number-of-additions-and-deletions-per-week func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo string) ([]*WeeklyStats, *Response, error) { u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo) 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 // 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-for-the-repository-owner-and-everyone-else func (s *RepositoriesService) ListParticipation(ctx context.Context, owner, repo string) (*RepositoryParticipation, *Response, error) { u := fmt.Sprintf("repos/%v/%v/stats/participation", owner, repo) 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 // 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-number-of-commits-per-hour-in-each-day func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo string) ([]*PunchCard, *Response, error) { u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo) req, err := s.client.NewRequest("GET", u, nil) diff --git a/github/repos_traffic.go b/github/repos_traffic.go index e7ee18849a5..91d85706286 100644 --- a/github/repos_traffic.go +++ b/github/repos_traffic.go @@ -118,7 +118,7 @@ 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. // -// GitHub API docs: https://developer.github.com/v3/repos/traffic/#views +// GitHub API docs: https://developer.github.com/v3/repos/traffic/#clones 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, err := addOptions(u, opts) diff --git a/github/search.go b/github/search.go index f08b3eb080a..c15c1f2b272 100644 --- a/github/search.go +++ b/github/search.go @@ -147,7 +147,7 @@ type IssuesSearchResult struct { // 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, opts *SearchOptions) (*IssuesSearchResult, *Response, error) { result := new(IssuesSearchResult) resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opts, result) diff --git a/github/teams.go b/github/teams.go index cfb814e7dbd..149fa570fc5 100644 --- a/github/teams.go +++ b/github/teams.go @@ -461,7 +461,7 @@ type TeamAddTeamRepoOptions struct { // 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 +// GitHub API docs: https://developer.github.com/v3/teams/#add-or-update-team-repository 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) @@ -476,7 +476,7 @@ func (s *TeamsService) AddTeamRepoByID(ctx context.Context, orgID, teamID int64, // 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 +// GitHub API docs: https://developer.github.com/v3/teams/#add-or-update-team-repository 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) @@ -491,7 +491,7 @@ func (s *TeamsService) AddTeamRepoBySlug(ctx context.Context, org, slug, owner, // 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-team-repo +// GitHub API docs: https://developer.github.com/v3/teams/#remove-team-repository 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) @@ -506,7 +506,7 @@ func (s *TeamsService) RemoveTeamRepoByID(ctx context.Context, orgID, teamID int // 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-team-repo +// GitHub API docs: https://developer.github.com/v3/teams/#remove-team-repository 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) @@ -767,7 +767,7 @@ func (s *TeamsService) ListIDPGroupsInOrganization(ctx context.Context, org stri // ListIDPGroupsForTeam lists IDP groups connected to a team on GitHub. // -// GitHub API docs: https://developer.github.com/v3/teams/team_sync/#list-idp-groups-for-a-team +// GitHub API docs: https://developer.github.com/v3/teams/team_sync/#list-idp-groups-for-a-team-legacy func (s *TeamsService) ListIDPGroupsForTeam(ctx context.Context, teamID string) (*IDPGroupList, *Response, error) { u := fmt.Sprintf("teams/%v/team-sync/group-mappings", teamID) @@ -787,7 +787,7 @@ func (s *TeamsService) ListIDPGroupsForTeam(ctx context.Context, teamID string) // CreateOrUpdateIDPGroupConnections creates, updates, or removes a connection between a team // and an IDP group. // -// GitHub API docs: https://developer.github.com/v3/teams/team_sync/#create-or-update-idp-group-connections +// GitHub API docs: https://developer.github.com/v3/teams/team_sync/#create-or-update-idp-group-connections-legacy func (s *TeamsService) CreateOrUpdateIDPGroupConnections(ctx context.Context, teamID string, opts IDPGroupList) (*IDPGroupList, *Response, error) { u := fmt.Sprintf("teams/%v/team-sync/group-mappings", teamID) diff --git a/github/users_gpg_keys.go b/github/users_gpg_keys.go index 1d4dab045af..68bdcf87c85 100644 --- a/github/users_gpg_keys.go +++ b/github/users_gpg_keys.go @@ -44,7 +44,7 @@ type GPGEmail struct { // string will fetch keys for the authenticated user. It requires authentication // via Basic Auth or via OAuth with at least read:gpg_key scope. // -// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#list-gpg-keys-for-a-user +// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#list-your-gpg-keys func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opts *ListOptions) ([]*GPGKey, *Response, error) { var u string if user != "" { diff --git a/github/users_keys.go b/github/users_keys.go index f12c01b9b07..d823125c289 100644 --- a/github/users_keys.go +++ b/github/users_keys.go @@ -27,7 +27,7 @@ func (k Key) String() string { // ListKeys lists the verified public keys for a user. Passing the empty // string will fetch keys for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user +// GitHub API docs: https://developer.github.com/v3/users/keys/#list-your-public-keys func (s *UsersService) ListKeys(ctx context.Context, user string, opts *ListOptions) ([]*Key, *Response, error) { var u string if user != "" { From d9d8cadff38410ca86ba003badd73b0257f0472c Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Sun, 29 Mar 2020 22:32:54 -0400 Subject: [PATCH 02/12] Add unit tests --- github/activity_events.go | 4 +- github/activity_star.go | 2 +- github/activity_watching.go | 2 +- github/apps_marketplace.go | 2 +- github/gen-doc-urls-activity-events_test.go | 1437 +++++++ github/gen-doc-urls-reactions_test.go | 4141 +++++++++++++++++++ github/gen-doc-urls.go | 619 ++- github/gen-doc-urls_test.go | 3604 +++------------- github/gists.go | 2 +- github/git_refs.go | 4 +- github/gitignore.go | 4 +- github/issues.go | 2 +- github/migrations_source_import.go | 16 +- github/orgs_members.go | 5 +- github/pulls.go | 2 + github/reactions.go | 10 +- github/repos.go | 4 +- github/repos_commits.go | 2 + github/repos_keys.go | 20 - github/users.go | 2 +- github/users_projects.go | 2 +- go.mod | 1 + go.sum | 2 + 23 files changed, 6602 insertions(+), 3287 deletions(-) create mode 100644 github/gen-doc-urls-activity-events_test.go create mode 100644 github/gen-doc-urls-reactions_test.go diff --git a/github/activity_events.go b/github/activity_events.go index 38f1d98c88b..d45b26ddcd8 100644 --- a/github/activity_events.go +++ b/github/activity_events.go @@ -59,7 +59,7 @@ func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo // 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-events-for-a-repository 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, err := addOptions(u, opts) @@ -132,6 +132,7 @@ func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org str // ListEventsPerformedByUser lists the events performed by a user. If publicOnly is // true, only public events will be returned. // +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-for-the-authenticated-user // 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 @@ -162,6 +163,7 @@ func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user st // ListEventsReceivedByUser lists the events received by a user. If publicOnly is // true, only public events will be returned. // +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-received-by-the-authenticated-user // 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 diff --git a/github/activity_star.go b/github/activity_star.go index 7f526e3aebe..4845adcabcd 100644 --- a/github/activity_star.go +++ b/github/activity_star.go @@ -67,7 +67,7 @@ type ActivityListStarredOptions struct { // ListStarred lists all the repos starred by a user. Passing the empty string // will list the starred repositories for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-repositories-starred-by-the-authenticated-useruser +// 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 if user != "" { diff --git a/github/activity_watching.go b/github/activity_watching.go index 4ff1a91b246..09036fdf68c 100644 --- a/github/activity_watching.go +++ b/github/activity_watching.go @@ -52,7 +52,7 @@ func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, // ListWatched lists the repositories the specified user is watching. Passing // the empty string will fetch watched repos for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-watched-by-the-authenticated-useruser +// 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 if user != "" { diff --git a/github/apps_marketplace.go b/github/apps_marketplace.go index 1c8ba2ffd06..898ad62eba5 100644 --- a/github/apps_marketplace.go +++ b/github/apps_marketplace.go @@ -150,7 +150,7 @@ func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, acc // ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user. // -// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-subscriptions-for-the-authenticated-user-stubbedticated-user +// 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" if s.Stubbed { diff --git a/github/gen-doc-urls-activity-events_test.go b/github/gen-doc-urls-activity-events_test.go new file mode 100644 index 00000000000..b3f30af259e --- /dev/null +++ b/github/gen-doc-urls-activity-events_test.go @@ -0,0 +1,1437 @@ +// -*- compile-command: "go test -v gen-doc-urls*.go"; -*- +// +build ignore + +package main + +import ( + "testing" +) + +func newActivitiesEventsPipeline() *pipelineSetup { + return &pipelineSetup{ + baseURL: "https://developer.github.com/v3/activity/events/", + endpointsFromWebsite: activityEventsWant, + filename: "activity_events.go", + serviceName: "ActivityService", + originalGoSource: activityEventsGoFileOriginal, + wantGoSource: activityEventsGoFileWant, + wantNumEndpoints: 7, + } +} + +func TestPipeline_ActivityEvents(t *testing.T) { + ps := newActivitiesEventsPipeline() + ps.setup(t, false, false) + ps.validate(t) +} + +func TestPipeline_ActivityEvents_FirstStripAllURLs(t *testing.T) { + ps := newActivitiesEventsPipeline() + ps.setup(t, true, false) + ps.validate(t) +} + +func TestPipeline_ActivityEvents_FirstDestroyReceivers(t *testing.T) { + ps := newActivitiesEventsPipeline() + ps.setup(t, false, true) + ps.validate(t) +} + +func TestPipeline_ActivityEvents_FirstStripAllURLsAndDestroyReceivers(t *testing.T) { + ps := newActivitiesEventsPipeline() + ps.setup(t, true, true) + ps.validate(t) +} + +func TestParseWebPageEndpoints_ActivityEvents(t *testing.T) { + got, want := parseWebPageEndpoints(activityEventsTestWebPage), activityEventsWant + testWebPageHelper(t, got, want) +} + +var activityEventsWant = endpointsByFragmentID{ + "list-public-events": []*Endpoint{ + {urlFormats: []string{"events"}, httpMethod: "GET"}, + }, + + "list-repository-events": []*Endpoint{ + {urlFormats: []string{"repos/%v/%v/events"}, httpMethod: "GET"}, + }, + + "list-public-events-for-a-network-of-repositories": []*Endpoint{ + {urlFormats: []string{"networks/%v/%v/events"}, httpMethod: "GET"}, + }, + + "list-events-received-by-the-authenticated-user": []*Endpoint{ + {urlFormats: []string{"users/%v/received_events"}, httpMethod: "GET"}, + }, + + "list-events-for-the-authenticated-user": []*Endpoint{ + {urlFormats: []string{"users/%v/events"}, httpMethod: "GET"}, + }, + + "list-public-events-for-a-user": []*Endpoint{ + {urlFormats: []string{"users/%v/events/public"}, httpMethod: "GET"}, + }, + + "list-organization-events-for-the-authenticated-user": []*Endpoint{ + {urlFormats: []string{"users/%v/events/orgs/%v"}, httpMethod: "GET"}, + }, + + "list-public-organization-events": []*Endpoint{ + {urlFormats: []string{"orgs/%v/events"}, httpMethod: "GET"}, + }, + + "list-public-events-received-by-a-user": []*Endpoint{ + {urlFormats: []string{"users/%v/received_events/public"}, httpMethod: "GET"}, + }, +} + +var activityEventsTestWebPage = ` + + + + + + + + Events | GitHub Developer Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+

+Events

+ +

This is a read-only API to the GitHub events. These events power the various activity streams on the site. An events API for repository issues is also available. For more information, see the "Issue Events API."

+ + + +

Events are optimized for polling with the "ETag" header. If no new events have been triggered, you will see a "304 Not Modified" response, and your current rate limit will be untouched. There is also an "X-Poll-Interval" header that specifies how often (in seconds) you are allowed to poll. In times of high +server load, the time may increase. Please obey the header.

+ +
+curl -I https://api.github.com/users/tater/events
+HTTP/1.1 200 OK
+X-Poll-Interval: 60
+ETag: "a18c3bded88eb5dbb5c849a489412bf3"
+# The quotes around the ETag value are important
+curl -I https://api.github.com/users/tater/events \
+   -H 'If-None-Match: "a18c3bded88eb5dbb5c849a489412bf3"'
+HTTP/1.1 304 Not Modified
+X-Poll-Interval: 60
+
+ +

Events support pagination, however the per_page option is unsupported. The fixed page size is 30 items. Fetching up to ten pages is supported, for a total of 300 events.

+ +

Only events created within the past 90 days will be included in timelines. Events older than 90 days will not be included (even if the total number of events in the timeline is less than 300).

+ +

All Events have the same response format:

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "type": "Event",
+    "public": true,
+    "payload": {
+    },
+    "repo": {
+      "id": 3,
+      "name": "octocat/Hello-World",
+      "url": "https://api.github.com/repos/octocat/Hello-World"
+    },
+    "actor": {
+      "id": 1,
+      "login": "octocat",
+      "gravatar_id": "",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "url": "https://api.github.com/users/octocat"
+    },
+    "org": {
+      "id": 1,
+      "login": "github",
+      "gravatar_id": "",
+      "url": "https://api.github.com/orgs/github",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif"
+    },
+    "created_at": "2011-09-06T17:26:27Z",
+    "id": "12345"
+  }
+]
+
+ + +

+List public events +

+ +

We delay the public events feed by five minutes, which means the most recent event returned by the public events API actually occurred at least five minutes ago.

+ +
GET /events
+
+ +

+List repository events +

+ +
GET /repos/:owner/:repo/events
+
+ +

+List public events for a network of repositories +

+ +
GET /networks/:owner/:repo/events
+
+ +

+List public organization events +

+ +
GET /orgs/:org/events
+
+ +

+List events received by the authenticated user +

+ +

These are events that you've received by watching repos and following users. If you are authenticated as the given user, you will see private events. Otherwise, you'll only see public events.

+ +
GET /users/:username/received_events
+
+ +

+List public events received by a user +

+ +
GET /users/:username/received_events/public
+
+ +

+List events for the authenticated user +

+ +

If you are authenticated as the given user, you will see your private events. Otherwise, you'll only see public events.

+ +
GET /users/:username/events
+
+ +

+List public events for a user +

+ +
GET /users/:username/events/public
+
+ +

+List organization events for the authenticated user

+ +

This is the user's organization dashboard. You must be authenticated as the user to view this.

+ +
GET /users/:username/events/orgs/:org
+
+
+ + + + + +
+
+ + + + + + + +` + +var activityEventsGoFileOriginal = `// Copyright 2013 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" +) + +// ListEvents drinks from the firehose of all public events across GitHub. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events +func (s *ActivityService) ListEvents(ctx context.Context, opts *ListOptions) ([]*Event, *Response, error) { + u, err := addOptions("events", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListRepositoryEvents lists events for a repository. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-repository-events +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, 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// Note that ActivityService.ListIssueEventsForRepository was moved to: +// IssuesService.ListRepositoryEvents. + +// 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 +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, 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsForOrganization lists public events for an organization. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-an-organization +func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("orgs/%v/events", 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-performed-by-a-user +func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) { + var u string + if publicOnly { + u = fmt.Sprintf("users/%v/events/public", user) + } else { + u = fmt.Sprintf("users/%v/events", user) + } + 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsReceivedByUser lists the events received by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-that-a-user-has-received +func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) { + var u string + if publicOnly { + u = fmt.Sprintf("users/%v/received_events/public", user) + } else { + u = fmt.Sprintf("users/%v/received_events", user) + } + 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListUserEventsForOrganization provides the user’s organization dashboard. You +// must be authenticated as the user to view this. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-for-an-organization +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, 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} +` + +var activityEventsGoFileWant = `// Copyright 2013 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" +) + +// ListEvents drinks from the firehose of all public events across GitHub. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events +func (s *ActivityService) ListEvents(ctx context.Context, opts *ListOptions) ([]*Event, *Response, error) { + u, err := addOptions("events", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListRepositoryEvents lists events for a repository. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-repository-events +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, 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// Note that ActivityService.ListIssueEventsForRepository was moved to: +// IssuesService.ListRepositoryEvents. + +// 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 +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, 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsForOrganization lists 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, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("orgs/%v/events", 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-for-the-authenticated-user +// 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 + if publicOnly { + u = fmt.Sprintf("users/%v/events/public", user) + } else { + u = fmt.Sprintf("users/%v/events", user) + } + 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsReceivedByUser lists the events received by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-received-by-the-authenticated-user +// 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 + if publicOnly { + u = fmt.Sprintf("users/%v/received_events/public", user) + } else { + u = fmt.Sprintf("users/%v/received_events", user) + } + 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListUserEventsForOrganization provides the user’s organization dashboard. You +// must be authenticated as the user to view this. +// +// 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, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("users/%v/events/orgs/%v", user, 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 events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} +` diff --git a/github/gen-doc-urls-reactions_test.go b/github/gen-doc-urls-reactions_test.go new file mode 100644 index 00000000000..6dd0fa48ea7 --- /dev/null +++ b/github/gen-doc-urls-reactions_test.go @@ -0,0 +1,4141 @@ +// -*- compile-command: "go test -v gen-doc-urls*.go"; -*- +// +build ignore + +package main + +import ( + "testing" +) + +func newReactionsPipeline() *pipelineSetup { + return &pipelineSetup{ + baseURL: "https://developer.github.com/v3/reactions/", + endpointsFromWebsite: reactionsWant, + filename: "reactions.go", + serviceName: "ReactionsService", + originalGoSource: reactionsGoFileOriginal, + wantGoSource: reactionsGoFileWant, + wantNumEndpoints: 25, + } +} + +func TestPipeline_Reactions(t *testing.T) { + ps := newReactionsPipeline() + ps.setup(t, false, false) + ps.validate(t) +} + +func TestPipeline_Reactions_FirstStripAllURLs(t *testing.T) { + ps := newReactionsPipeline() + ps.setup(t, true, false) + ps.validate(t) +} + +func TestPipeline_Reactions_FirstDestroyReceivers(t *testing.T) { + ps := newReactionsPipeline() + ps.setup(t, false, true) + ps.validate(t) +} + +func TestPipeline_Reactions_FirstStripAllURLsAndDestroyReceivers(t *testing.T) { + ps := newReactionsPipeline() + ps.setup(t, true, true) + ps.validate(t) +} + +func TestParseWebPageEndpoints_Reactions(t *testing.T) { + got, want := parseWebPageEndpoints(reactionsTestWebPage), reactionsWant + testWebPageHelper(t, got, want) +} + +var reactionsWant = endpointsByFragmentID{ + "list-reactions-for-a-commit-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/comments/%v/reactions"}, httpMethod: "GET"}}, + + "delete-a-commit-comment-reaction": []*Endpoint{ + {urlFormats: []string{"repositories/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"repos/%v/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "create-reaction-for-an-issue": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/%v/reactions"}, httpMethod: "POST"}}, + + "delete-an-issue-reaction": []*Endpoint{ + {urlFormats: []string{"repositories/%v/issues/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"repos/%v/%v/issues/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "create-reaction-for-a-pull-request-review-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/pulls/comments/%v/reactions"}, httpMethod: "POST"}}, + + "list-reactions-for-a-team-discussion": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/reactions"}, httpMethod: "GET"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/reactions"}, httpMethod: "GET"}, + }, + + "delete-a-reaction-legacy": []*Endpoint{{urlFormats: []string{"reactions/%v"}, httpMethod: "DELETE"}}, + + "list-reactions-for-a-team-discussion-comment-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "GET"}}, + + "delete-an-issue-comment-reaction": []*Endpoint{ + {urlFormats: []string{"repositories/%v/issues/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"repos/%v/%v/issues/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "list-reactions-for-a-pull-request-review-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/pulls/comments/%v/reactions"}, httpMethod: "GET"}}, + + "create-reaction-for-a-team-discussion-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/reactions"}, httpMethod: "POST"}}, + + "create-reaction-for-a-team-discussion-comment-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "POST"}}, + + "create-reaction-for-a-commit-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/comments/%v/reactions"}, httpMethod: "POST"}}, + + "list-reactions-for-an-issue": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/%v/reactions"}, httpMethod: "GET"}}, + + "create-reaction-for-an-issue-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/comments/%v/reactions"}, httpMethod: "POST"}}, + + "create-reaction-for-a-team-discussion": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/reactions"}, httpMethod: "POST"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/reactions"}, httpMethod: "POST"}, + }, + + "delete-team-discussion-reaction": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "create-reaction-for-a-team-discussion-comment": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "POST"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "POST"}, + }, + + "list-reactions-for-an-issue-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/comments/%v/reactions"}, httpMethod: "GET"}}, + + "delete-a-pull-request-comment-reaction": []*Endpoint{ + {urlFormats: []string{"repositories/%v/pulls/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"repos/%v/%v/pulls/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "list-reactions-for-a-team-discussion-comment": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "GET"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "GET"}, + }, + + "delete-team-discussion-comment-reaction": []*Endpoint{ + {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, + }, + + "list-reactions-for-a-team-discussion-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/reactions"}, httpMethod: "GET"}}, +} + +var reactionsTestWebPage = ` + + + + + + + + + Reactions | GitHub Developer Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+

+ Reactions

+ + + +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

+ Reaction types

+ +

When creating a reaction, the allowed values for the content parameter are as follows (with the + corresponding emoji for reference):

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
contentemoji
+1:+1:
-1:-1:
laugh:smile:
confused:confused:
heart:heart:
hooray:tada:
rocket:rocket:
eyes:eyes:
+ +

+ List reactions for a + commit comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a commit comment.

+ +
GET /repos/:owner/:repo/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a commit comment.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a + commit comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a commit comment. A response with a + Status: 200 OK means that you already added the reaction type to this commit comment.

+ +
POST /repos/:owner/:repo/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + commit comment.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete a commit comment + reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a repository by repository_id using the route + DELETE /repositories/:repository_id/comments/:comment_id/reactions/:reaction_id.

+ +
+ +

Delete a reaction to a commit comment.

+ +
DELETE /repos/:owner/:repo/comments/:comment_id/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for an + issue +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to an issue.

+ +
GET /repos/:owner/:repo/issues/:issue_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to an issue.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for an + issue

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to an issue. A response with a Status: 200 OK means + that you already added the reaction type to this issue.

+ +
POST /repos/:owner/:repo/issues/:issue_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + issue.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete an issue reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a repository by repository_id using the route + DELETE /repositories/:repository_id/issues/:issue_number/reactions/:reaction_id.

+ +
+ +

Delete a reaction to an issue.

+ +
DELETE /repos/:owner/:repo/issues/:issue_number/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for an + issue comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to an issue comment.

+ +
GET /repos/:owner/:repo/issues/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to an issue comment.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for an + issue comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to an issue comment. A response with a + Status: 200 OK means that you already added the reaction type to this issue comment.

+ +
POST /repos/:owner/:repo/issues/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + issue comment.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete an issue comment + reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a repository by repository_id using the route + DELETE delete /repositories/:repository_id/issues/comments/:comment_id/reactions/:reaction_id. +

+ +
+ +

Delete a reaction to an issue comment.

+ +
DELETE /repos/:owner/:repo/issues/comments/:comment_id/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for a pull request review comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a pull request review comment.

+ +
GET /repos/:owner/:repo/pulls/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a pull request review comment.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a pull request review comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a pull request review comment. A response with a + Status: 200 OK means that you already added the reaction type to this pull request review + comment.

+ +
POST /repos/:owner/:repo/pulls/comments/:comment_id/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + pull request review comment.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete a pull request + comment reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a repository by repository_id using the route + DELETE /repositories/:repository_id/pulls/comments/:comment_id/reactions/:reaction_id.

+ +
+ +

Delete a reaction to a pull request review comment.

+ +
DELETE /repos/:owner/:repo/pulls/comments/:comment_id/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for a + team discussion +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a team discussion. OAuth access tokens require the + read:discussion scope.

+ +
+ +

Note: You can also specify a team by org_id and team_id using + the route GET /organizations/:org_id/team/:team_id/discussions/:discussion_number/reactions. +

+ +
+ +
GET /orgs/:org/teams/:team_slug/discussions/:discussion_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a team discussion.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a + team discussion

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a team discussion. OAuth access tokens require the + write:discussion scope. A response with a + Status: 200 OK means that you already added the reaction type to this team discussion.

+ +
+ +

Note: You can also specify a team by org_id and team_id using + the route POST /organizations/:org_id/team/:team_id/discussions/:discussion_number/reactions. +

+ +
+ +
POST /orgs/:org/teams/:team_slug/discussions/:discussion_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + team discussion.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete team discussion + reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a team or organization with team_id and + org_id using the route + DELETE /organizations/:org_id/team/:team_id/discussions/:discussion_number/reactions/:reaction_id. +

+ +
+ +

Delete a reaction to a team discussion. OAuth access tokens require the + write:discussion scope.

+ +
DELETE /orgs/:org/teams/:team_slug/discussions/:discussion_number/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for a team discussion comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a team discussion comment. OAuth access + tokens require the read:discussion scope.

+ +
+ +

Note: You can also specify a team by org_id and team_id using + the route + GET /organizations/:org_id/team/:team_id/discussions/:discussion_number/comments/:comment_number/reactions. +

+ +
+ +
GET /orgs/:org/teams/:team_slug/discussions/:discussion_number/comments/:comment_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a team discussion comment.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a team discussion comment +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a team discussion comment. OAuth access + tokens require the write:discussion scope. A response with a + Status: 200 OK means that you already added the reaction type to this team discussion comment. +

+ +
+ +

Note: You can also specify a team by org_id and team_id using + the route + POST /organizations/:org_id/team/:team_id/discussions/:discussion_number/comments/:comment_number/reactions. +

+ +
+ +
POST /orgs/:org/teams/:team_slug/discussions/:discussion_number/comments/:comment_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + team discussion comment.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ Delete team discussion + comment reaction +

+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +
+ +

Note: You can also specify a team or organization with team_id and + org_id using the route + DELETE /organizations/:org_id/team/:team_id/discussions/:discussion_number/comments/:comment_number/reactions/:reaction_id. +

+ +
+ +

Delete a reaction to a team discussion comment. OAuth access + tokens require the write:discussion scope.

+ +
DELETE /orgs/:org/teams/:team_slug/discussions/:discussion_number/comments/:comment_number/reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ Delete a reaction (Legacy) +

+ +
+ +

Deprecation Notice: This endpoint route is deprecated and will be removed from the + Reactions API. We recommend migrating your existing code to use the new delete reactions endpoints. For more + information, see this blog post.

+ +
+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

OAuth access tokens require the write:discussion scope, when deleting a team discussion or team + discussion comment.

+ +
DELETE /reactions/:reaction_id
+
+ +

+ Response

+ +
Status: 204 No Content
+
+ + +

+ List reactions for a team discussion (Legacy) +

+ +
+ +

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams + API. We recommend migrating your existing code to use the new List reactions for a team discussion + endpoint.

+ +
+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a team discussion. OAuth access tokens require the + read:discussion scope.

+ +
GET /teams/:team_id/discussions/:discussion_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a team discussion.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a team discussion (Legacy)

+ +
+ +

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams + API. We recommend migrating your existing code to use the new Create reaction for a team discussion + endpoint.

+ +
+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a team discussion. OAuth access tokens require the + write:discussion scope. A response with a + Status: 200 OK means that you already added the reaction type to this team discussion.

+ +
POST /teams/:team_id/discussions/:discussion_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + team discussion.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ + +

+ List reactions for a team discussion comment (Legacy) +

+ +
+ +

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams + API. We recommend migrating your existing code to use the new List reactions for a team discussion comment + endpoint.

+ +
+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

List the reactions to a team discussion comment. OAuth access + tokens require the read:discussion scope.

+ +
GET /teams/:team_id/discussions/:discussion_number/comments/:comment_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to + list all reactions to a team discussion comment.
+ +

+ Response

+ +
Status: 200 OK
+Link: <https://api.github.com/resource?page=2>; rel="next",
+      <https://api.github.com/resource?page=5>; rel="last"
+
+ + +
[
+  {
+    "id": 1,
+    "node_id": "MDg6UmVhY3Rpb24x",
+    "user": {
+      "login": "octocat",
+      "id": 1,
+      "node_id": "MDQ6VXNlcjE=",
+      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+      "gravatar_id": "",
+      "url": "https://api.github.com/users/octocat",
+      "html_url": "https://github.com/octocat",
+      "followers_url": "https://api.github.com/users/octocat/followers",
+      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+      "organizations_url": "https://api.github.com/users/octocat/orgs",
+      "repos_url": "https://api.github.com/users/octocat/repos",
+      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+      "received_events_url": "https://api.github.com/users/octocat/received_events",
+      "type": "User",
+      "site_admin": false
+    },
+    "content": "heart",
+    "created_at": "2016-05-20T20:09:31Z"
+  }
+]
+
+ + +

+ Create reaction for a team discussion comment (Legacy) +

+ +
+ +

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams + API. We recommend migrating your existing code to use the new Create reaction for a team discussion comment + endpoint.

+ +
+ +
+ +

Note: APIs for managing reactions are currently available for developers to preview. See + the blog post for full details. To access the API + during the preview period, you must provide a custom media type in the + Accept header:

+ +
  application/vnd.github.squirrel-girl-preview+json
+
+ +
+ +
+ +

Warning: The API may change without advance notice during the preview period. Preview + features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub + Premium Support.

+ +
+ +

Create a reaction to a team discussion comment. OAuth access + tokens require the write:discussion scope. A response with a + Status: 200 OK means that you already added the reaction type to this team discussion comment. +

+ +
POST /teams/:team_id/discussions/:discussion_number/comments/:comment_number/reactions
+
+ +

+ Parameters

+ + + + + + + + + + + + + + + + +
NameTypeDescription
contentstring + Required. The reaction type to add to the + team discussion comment.
+ +

+ Example

+ +
{
+  "content": "heart"
+}
+
+ + +

+ Response

+ +
Status: 201 Created
+
+ + +
{
+  "id": 1,
+  "node_id": "MDg6UmVhY3Rpb24x",
+  "user": {
+    "login": "octocat",
+    "id": 1,
+    "node_id": "MDQ6VXNlcjE=",
+    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
+    "gravatar_id": "",
+    "url": "https://api.github.com/users/octocat",
+    "html_url": "https://github.com/octocat",
+    "followers_url": "https://api.github.com/users/octocat/followers",
+    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+    "organizations_url": "https://api.github.com/users/octocat/orgs",
+    "repos_url": "https://api.github.com/users/octocat/repos",
+    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+    "received_events_url": "https://api.github.com/users/octocat/received_events",
+    "type": "User",
+    "site_admin": false
+  },
+  "content": "heart",
+  "created_at": "2016-05-20T20:09:31Z"
+}
+
+ +
+ + + + + +
+
+ + + + + + + + +` + +var reactionsGoFileOriginal = `// 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" + "net/http" +) + +// ReactionsService provides access to the reactions-related functions in the +// GitHub API. +type ReactionsService service + +// Reaction represents a GitHub reaction. +type Reaction struct { + // ID is the Reaction ID. + ID *int64 ` + "`" + `json:"id,omitempty"` + "`" + ` + User *User ` + "`" + `json:"user,omitempty"` + "`" + ` + NodeID *string ` + "`" + `json:"node_id,omitempty"` + "`" + ` + // Content is the type of reaction. + // Possible values are: + // "+1", "-1", "laugh", "confused", "heart", "hooray". + Content *string ` + "`" + `json:"content,omitempty"` + "`" + ` +} + +// Reactions represents a summary of GitHub reactions. +type Reactions struct { + TotalCount *int ` + "`" + `json:"total_count,omitempty"` + "`" + ` + PlusOne *int ` + "`" + `json:"+1,omitempty"` + "`" + ` + MinusOne *int ` + "`" + `json:"-1,omitempty"` + "`" + ` + Laugh *int ` + "`" + `json:"laugh,omitempty"` + "`" + ` + Confused *int ` + "`" + `json:"confused,omitempty"` + "`" + ` + Heart *int ` + "`" + `json:"heart,omitempty"` + "`" + ` + Hooray *int ` + "`" + `json:"hooray,omitempty"` + "`" + ` + URL *string ` + "`" + `json:"url,omitempty"` + "`" + ` +} + +func (r Reaction) String() string { + 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. +// +// 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, opts *ListCommentReactionOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + 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 headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateCommentReaction creates a reaction for a commit comment. +// Note that if you have already created a reaction of type content, the +// 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". +// +// 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) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + 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. +// +// 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, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + 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 headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueReaction creates a reaction for an issue. +// Note that if you have already created a reaction of type content, the +// 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". +// +// 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) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + 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. +// +// 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, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + 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 headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueCommentReaction creates a reaction for an issue comment. +// Note that if you have already created a reaction of type content, the +// 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". +// +// 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) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + 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. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment +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, 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 headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreatePullRequestCommentReaction creates a reaction for a pull request review comment. +// Note that if you have already created a reaction of type content, the +// 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". +// +// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment +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) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + 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. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-team-discussion +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, 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 + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateTeamDiscussionReaction creates a reaction for a team discussion. +// 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 +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) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + 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. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-team-discussion-comment +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, 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 + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, nil, err + } + return m, resp, nil +} + +// CreateTeamDiscussionCommentReaction creates a reaction for a team discussion comment. +// 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 +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) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteTeamDiscussionCommentReaction deletes the reaction to a team discussion comment. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#delete-team-discussion-comment-reaction +func (s *ReactionsService) DeleteTeamDiscussionCommentReaction(ctx context.Context, org, teamSlug string, discussionNumber, commentNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v/reactions/%v", org, teamSlug, discussionNumber, commentNumber, reactionID) + + 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 { + return nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + return s.client.Do(ctx, req, nil) +} +` + +var reactionsGoFileWant = `// 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" + "net/http" +) + +// ReactionsService provides access to the reactions-related functions in the +// GitHub API. +type ReactionsService service + +// Reaction represents a GitHub reaction. +type Reaction struct { + // ID is the Reaction ID. + ID *int64 ` + "`" + `json:"id,omitempty"` + "`" + ` + User *User ` + "`" + `json:"user,omitempty"` + "`" + ` + NodeID *string ` + "`" + `json:"node_id,omitempty"` + "`" + ` + // Content is the type of reaction. + // Possible values are: + // "+1", "-1", "laugh", "confused", "heart", "hooray". + Content *string ` + "`" + `json:"content,omitempty"` + "`" + ` +} + +// Reactions represents a summary of GitHub reactions. +type Reactions struct { + TotalCount *int ` + "`" + `json:"total_count,omitempty"` + "`" + ` + PlusOne *int ` + "`" + `json:"+1,omitempty"` + "`" + ` + MinusOne *int ` + "`" + `json:"-1,omitempty"` + "`" + ` + Laugh *int ` + "`" + `json:"laugh,omitempty"` + "`" + ` + Confused *int ` + "`" + `json:"confused,omitempty"` + "`" + ` + Heart *int ` + "`" + `json:"heart,omitempty"` + "`" + ` + Hooray *int ` + "`" + `json:"hooray,omitempty"` + "`" + ` + URL *string ` + "`" + `json:"url,omitempty"` + "`" + ` +} + +func (r Reaction) String() string { + 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. +// +// 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, opts *ListCommentReactionOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + 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 headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateCommentReaction creates a reaction for a commit comment. +// Note that if you have already created a reaction of type content, the +// 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". +// +// 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) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + 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. +// +// 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, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + 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 headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueReaction creates a reaction for an issue. +// Note that if you have already created a reaction of type content, the +// 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". +// +// 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) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + 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. +// +// 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, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + 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 headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueCommentReaction creates a reaction for an issue comment. +// Note that if you have already created a reaction of type content, the +// 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". +// +// 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) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + 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. +// +// 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, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) + 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 headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreatePullRequestCommentReaction creates a reaction for a pull request review comment. +// Note that if you have already created a reaction of type content, the +// 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". +// +// 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) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + 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. +// +// 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, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) + 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 + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateTeamDiscussionReaction creates a reaction for a team discussion. +// 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-legacy +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) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + 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. +// +// 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, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) + 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 + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, nil, err + } + return m, resp, nil +} + +// CreateTeamDiscussionCommentReaction creates a reaction for a team discussion comment. +// 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-legacy +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) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteTeamDiscussionCommentReaction deletes the reaction to a team discussion comment. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#delete-team-discussion-comment-reaction +func (s *ReactionsService) DeleteTeamDiscussionCommentReaction(ctx context.Context, org, teamSlug string, discussionNumber, commentNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v/reactions/%v", org, teamSlug, discussionNumber, commentNumber, reactionID) + + 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 { + return nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + return s.client.Do(ctx, req, nil) +} +` diff --git a/github/gen-doc-urls.go b/github/gen-doc-urls.go index 767d9b0ffbd..6d223f45348 100644 --- a/github/gen-doc-urls.go +++ b/github/gen-doc-urls.go @@ -16,6 +16,7 @@ package main import ( + "errors" "flag" "fmt" "go/ast" @@ -41,14 +42,40 @@ const ( ) var ( - verbose = flag.Bool("v", false, "Print verbose log messages") + verbose = flag.Bool("v", false, "Print verbose log messages") + debugFile = flag.String("d", "", "Debug named file only") - // methodBlacklist holds methods that do not have GitHub v3 API URLs. + // methodBlacklist holds methods that do not have GitHub v3 API URLs + // or are otherwise problematic in parsing, discovering, and/or fixing. methodBlacklist = map[string]bool{ - "MarketplaceService.marketplaceURI": true, - "RepositoriesService.DownloadContents": true, - "SearchService.search": true, - "UsersService.GetByID": true, + "ActionsService.DownloadArtifact": true, + "AdminService.CreateOrg": true, + "AdminService.CreateUser": true, + "AdminService.CreateUserImpersonation": true, + "AdminService.DeleteUserImpersonation": true, + "AdminService.GetAdminStats": true, + "AdminService.UpdateTeamLDAPMapping": true, + "AdminService.UpdateUserLDAPMapping": true, + "AppsService.FindRepositoryInstallationByID": true, + "AuthorizationsService.CreateImpersonation": true, + "AuthorizationsService.DeleteImpersonation": true, + "GitService.GetRefs": true, + "GitService.ListRefs": true, + "MarketplaceService.marketplaceURI": true, + "OrganizationsService.GetByID": true, + "RepositoriesService.DeletePreReceiveHook": true, + "RepositoriesService.DownloadContents": true, + "RepositoriesService.GetArchiveLink": true, + "RepositoriesService.GetByID": true, + "RepositoriesService.GetPreReceiveHook": true, + "RepositoriesService.ListPreReceiveHooks": true, + "RepositoriesService.UpdatePreReceiveHook": true, + "SearchService.search": true, + "UsersService.DemoteSiteAdmin": true, + "UsersService.GetByID": true, + "UsersService.PromoteSiteAdmin": true, + "UsersService.Suspend": true, + "UsersService.Unsuspend": true, } helperOverrides = map[string]overrideFunc{ @@ -59,8 +86,8 @@ var ( // methodOverrides contains overrides for troublesome endpoints. methodOverrides = map[string]string{ - "OrganizationsService.EditOrgMembership: method orgs/%v/memberships/%v": "PUT", - "OrganizationsService.EditOrgMembership: method user/memberships/orgs/%v": "PATCH", + "OrganizationsService.EditOrgMembership: method orgs/%v/memberships/%v": "PUT", + "OrganizationsService.EditOrgMembership: PUT user/memberships/orgs/%v": "PATCH", } paramRE = regexp.MustCompile(`:[a-z_]+`) @@ -88,115 +115,54 @@ func main() { pkgs, err := parser.ParseDir(fset, ".", sourceFilter, parser.ParseComments) if err != nil { log.Fatal(err) - return } // Step 1 - get a map of all services. - services := servicesMap{} - for _, pkg := range pkgs { - for filename, f := range pkg.Files { - if filename != "github.go" { - continue - } - - logf("Step 1 - Processing %v ...", filename) - if err := findClientServices(filename, f, services); err != nil { - log.Fatal(err) - } - } - } + services := findAllServices(pkgs) // Step 2 - find all the API service endpoints. - endpoints := endpointsMap{} - for _, pkg := range pkgs { - for filename, f := range pkg.Files { - if filename == "github.go" { - continue - } - - if filename != "activity_events.go" { // DEBUGGING ONLY!!! - continue - } - - logf("Step 2 - Processing %v ...", filename) - if err := processAST(filename, f, services, endpoints); err != nil { - log.Fatal(err) - } - } + iter := &realAstFileIterator{fset: fset, pkgs: pkgs} + endpoints, err := findAllServiceEndpoints(iter, services) + if err != nil { + log.Fatalf("\n%v", err) } - apiDocs := map[string]map[string][]*Endpoint{} // cached by URL, then mapped by web fragment identifier. - urlByMethodAndPath := map[string]string{} - cacheDocs := func(s string) { - url := getURL(s) - if _, ok := apiDocs[url]; ok { - return - } + // Step 3 - resolve all missing httpMethods from helperMethods. + // Additionally, use existing URLs as hints to pre-cache all apiDocs. + docCache := &documentCache{} + usedHelpers, endpointsByFilename := resolveHelpersAndCacheDocs(endpoints, docCache) - // TODO: Enterprise URLs are currently causing problems - for example: - // GET https://developer.github.com/enterprise/v3/enterprise-admin/users/ - // returns StatusCode=404 - if strings.Contains(url, "enterprise") { - logf("Skipping troublesome Enterprise URL: %v", url) - return - } + // Step 4 - validate and rewrite all URLs, skipping used helper methods. + frw := &liveFileRewriter{fset: fset} + validateRewriteURLs(usedHelpers, endpointsByFilename, docCache, frw) - logf("GET %q ...", url) - resp, err := http.Get(url) - check("Unable to get URL: %v: %v", url, err) - if resp.StatusCode != http.StatusOK { - log.Fatalf("url %v - StatusCode=%v", url, resp.StatusCode) - } + logf("Done.") +} - b, err := ioutil.ReadAll(resp.Body) - check("Unable to read body of URL: %v, %v", url, err) - check("Unable to close body of URL: %v, %v", url, resp.Body.Close()) - apiDocs[url] = parseWebPageEndpoints(string(b)) - - // Now reverse-map the methods+paths to URLs. - for fragID, v := range apiDocs[url] { - for _, endpoint := range v { - for _, path := range endpoint.urlFormats { - methodAndPath := fmt.Sprintf("%v %v", endpoint.httpMethod, path) - urlByMethodAndPath[methodAndPath] = fmt.Sprintf("%v#%v", url, fragID) - logf("urlByMethodAndPath[%q] = %q", methodAndPath, urlByMethodAndPath[methodAndPath]) - } - } - } - } +type usedHelpersMap map[string]bool +type endpointsByFilenameMap map[string][]*Endpoint - // Step 3 - resolve all missing httpMethods from helperMethods. - // Additionally, use existing URLs as hints to pre-cache all apiDocs. - usedHelpers := map[string]bool{} - endpointsByFilename := map[string][]*Endpoint{} - for k, v := range endpoints { - if _, ok := endpointsByFilename[v.filename]; !ok { - endpointsByFilename[v.filename] = []*Endpoint{} - } - endpointsByFilename[v.filename] = append(endpointsByFilename[v.filename], v) +// FileRewriter read/writes files and converts AST token positions. +type FileRewriter interface { + Position(token.Pos) token.Position + ReadFile(filename string) ([]byte, error) + WriteFile(filename string, buf []byte, mode os.FileMode) error +} - for _, cmt := range v.enterpriseRefLines { - cacheDocs(cmt.Text) - } - for _, cmt := range v.stdRefLines { - cacheDocs(cmt.Text) - } +// liveFileRewriter implements FileRewriter. +type liveFileRewriter struct { + fset *token.FileSet +} - if v.httpMethod == "" && v.helperMethod != "" { - fullName := fmt.Sprintf("%v.%v", v.serviceName, v.helperMethod) - hm, ok := endpoints[fullName] - if !ok { - log.Fatalf("Unable to find helper method %q for %q", fullName, k) - } - if hm.httpMethod == "" { - log.Fatalf("Helper method %q for %q has empty httpMethod: %#v", fullName, k, hm) - } - v.httpMethod = hm.httpMethod - usedHelpers[fullName] = true - } - } +func (lfr *liveFileRewriter) Position(pos token.Pos) token.Position { return lfr.fset.Position(pos) } +func (lfr *liveFileRewriter) ReadFile(filename string) ([]byte, error) { + return ioutil.ReadFile(filename) +} +func (lfr *liveFileRewriter) WriteFile(filename string, buf []byte, mode os.FileMode) error { + return ioutil.WriteFile(filename, buf, mode) +} - // Step 4 - validate and rewrite all URLs, skipping used helper methods. +func validateRewriteURLs(usedHelpers usedHelpersMap, endpointsByFilename endpointsByFilenameMap, docCache documentCacheReader, fileRewriter FileRewriter) { for filename, slc := range endpointsByFilename { logf("Step 4 - Processing %v methods in %v ...", len(slc), filename) @@ -212,10 +178,19 @@ func main() { for _, path := range endpoint.urlFormats { path = strings.ReplaceAll(path, "%d", "%v") path = strings.ReplaceAll(path, "%s", "%v") + + // Check the overrides. + endpoint.checkHttpMethodOverride(path) + methodAndPath := fmt.Sprintf("%v %v", endpoint.httpMethod, path) - url, ok := urlByMethodAndPath[methodAndPath] + url, ok := docCache.UrlByMethodAndPath(methodAndPath) if !ok { - log.Printf("WARNING: Unable to find documentation for %v - %q: (%v)", filename, fullName, methodAndPath) + if i := len(endpoint.endpointComments); i > 0 { + pos := fileRewriter.Position(endpoint.endpointComments[i-1].Pos()) + fmt.Printf("%v:%v:%v: WARNING: unable to find online docs for %q: (%v)\nPLEASE CHECK MANUALLY AND FIX.\n", pos.Filename, pos.Line, pos.Column, fullName, methodAndPath) + } else { + fmt.Printf("%v: WARNING: unable to find online docs for %q: (%v)\nPLEASE CHECK MANUALLY AND FIX.\n", filename, fullName, methodAndPath) + } continue } logf("found %q for: %q (%v)", url, fullName, methodAndPath) @@ -228,62 +203,365 @@ func main() { line := fmt.Sprintf(enterpriseRefFmt, url) cmt := endpoint.enterpriseRefLines[0] if cmt.Text != line { - log.Printf("At token.pos=%v:\nFOUND %q\nWANT: %q", cmt.Pos(), cmt.Text, line) + pos := fileRewriter.Position(cmt.Pos()) + logf("At byte offset %v:\nFOUND %q\nWANT: %q", pos.Offset, cmt.Text, line) fileEdits = append(fileEdits, &FileEdit{ - pos: fset.Position(cmt.Pos()), + pos: pos, fromText: cmt.Text, toText: line, }) } case len(endpoint.stdRefLines) > 1: - log.Printf("WARNING: multiple GitHub URLs found - skipping: %#v", endpoint.stdRefLines) + var foundMatch bool + line := fmt.Sprintf(stdRefFmt, url) + for i, stdRefLine := range endpoint.stdRefLines { + if stdRefLine.Text == line { + foundMatch = true + logf("found match with %v, not editing and removing from list", line) + // Remove matching line + endpoint.stdRefLines = append(endpoint.stdRefLines[:i], endpoint.stdRefLines[i+1:]...) + break + } + } + if !foundMatch { // Edit last stdRefLine, then remove it. + cmt := endpoint.stdRefLines[len(endpoint.stdRefLines)-1] + pos := fileRewriter.Position(cmt.Pos()) + logf("At byte offset %v:\nFOUND %q\nWANT: %q", pos.Offset, cmt.Text, line) + fileEdits = append(fileEdits, &FileEdit{ + pos: pos, + fromText: cmt.Text, + toText: line, + }) + endpoint.stdRefLines = endpoint.stdRefLines[:len(endpoint.stdRefLines)-1] + } case len(endpoint.stdRefLines) > 0: line := fmt.Sprintf(stdRefFmt, url) cmt := endpoint.stdRefLines[0] if cmt.Text != line { - log.Printf("At token.pos=%v:\nFOUND %q\nWANT: %q", cmt.Pos(), cmt.Text, line) + pos := fileRewriter.Position(cmt.Pos()) + logf("At byte offset %v:\nFOUND %q\nWANT: %q", pos.Offset, cmt.Text, line) fileEdits = append(fileEdits, &FileEdit{ - pos: fset.Position(cmt.Pos()), + pos: pos, fromText: cmt.Text, toText: line, }) } + case len(endpoint.endpointComments) > 0: + lastCmt := endpoint.endpointComments[len(endpoint.endpointComments)-1] + // logf("lastCmt.Text=%q (len=%v)", lastCmt.Text, len(lastCmt.Text)) + pos := fileRewriter.Position(lastCmt.Pos()) + pos.Offset += len(lastCmt.Text) + line := "\n" + fmt.Sprintf(stdRefFmt, url) + if lastCmt.Text != "//" { + line = "\n//" + line // Add blank comment line before URL. + } + // logf("line=%q (len=%v)", line, len(line)) + // logf("At byte offset %v: adding missing documentation:\n%q", pos.Offset, line) + fileEdits = append(fileEdits, &FileEdit{ + pos: pos, + fromText: "", + toText: line, + }) default: // Missing documentation - add it. - log.Printf("TODO: Add missing documentation: %q for: %q (%v)", url, fullName, methodAndPath) + log.Printf("WARNING: file %v has no godoc comment string for method %v", fullName, methodAndPath) } } } if len(fileEdits) > 0 { - logf("Performing %v edits on file %v", len(fileEdits), filename) - // Sort edits from last to first in the file. - sort.Slice(fileEdits, func(a, b int) bool { return fileEdits[b].pos.Offset < fileEdits[a].pos.Offset }) - - b, err := ioutil.ReadFile(filename) + b, err := fileRewriter.ReadFile(filename) if err != nil { log.Fatalf("ReadFile: %v", err) } - var lastOffset int - for _, edit := range fileEdits { - if edit.pos.Offset == lastOffset { - logf("TODO: At offset %v, inserting second URL of %v bytes", edit.pos.Offset, len(edit.fromText), len(edit.toText)) - continue + log.Printf("Performing %v edits on file %v", len(fileEdits), filename) + b = performBufferEdits(b, fileEdits) + + if err := fileRewriter.WriteFile(filename, b, 0644); err != nil { + log.Fatalf("WriteFile: %v", err) + } + } + } +} + +func performBufferEdits(b []byte, fileEdits []*FileEdit) []byte { + fileEdits = sortAndMergeFileEdits(fileEdits) + + for _, edit := range fileEdits { + prelude := b[0:edit.pos.Offset] + postlude := b[edit.pos.Offset+len(edit.fromText):] + logf("At byte offset %v, replacing %v bytes with %v bytes\nBEFORE: %v\nAFTER : %v", edit.pos.Offset, len(edit.fromText), len(edit.toText), edit.fromText, edit.toText) + b = []byte(fmt.Sprintf("%s%v%s", prelude, edit.toText, postlude)) + } + + return b +} + +func sortAndMergeFileEdits(fileEdits []*FileEdit) []*FileEdit { + // Sort edits from last to first in the file. + // If the offsets are identical, sort the comment "toText" strings, ascending. + var foundDups bool + sort.Slice(fileEdits, func(a, b int) bool { + if fileEdits[a].pos.Offset == fileEdits[b].pos.Offset { + foundDups = true + return fileEdits[a].toText < fileEdits[b].toText + } + return fileEdits[a].pos.Offset > fileEdits[b].pos.Offset + }) + + if !foundDups { + return fileEdits + } + + // Merge the duplicate edits. + var mergedEdits []*FileEdit + var dupOffsets []*FileEdit + + mergeFunc := func() { + if len(dupOffsets) > 1 { + isInsert := dupOffsets[0].fromText == "" + var hasBlankCommentLine bool + + // Merge dups + var lines []string + for _, dup := range dupOffsets { + if isInsert && strings.HasPrefix(dup.toText, "\n//\n//") { + lines = append(lines, strings.TrimPrefix(dup.toText, "\n//")) + hasBlankCommentLine = true + } else { + lines = append(lines, dup.toText) } - lastOffset = edit.pos.Offset - logf("At offset %v, replacing %v bytes with %v bytes", edit.pos.Offset, len(edit.fromText), len(edit.toText)) - before := b[0:edit.pos.Offset] - after := b[edit.pos.Offset+len(edit.fromText):] - b = []byte(fmt.Sprintf("%s%v%s", before, edit.toText, after)) } + sort.Strings(lines) - if err := ioutil.WriteFile(filename, b, 0644); err != nil { - log.Fatalf("WriteFile: %v", err) + var joinStr string + // if insert, no extra newlines + if !isInsert { // if replacement - add newlines + joinStr = "\n" } + toText := strings.Join(lines, joinStr) + if hasBlankCommentLine { // Add back in + toText = "\n//" + toText + } + mergedEdits = append(mergedEdits, &FileEdit{ + pos: dupOffsets[0].pos, + fromText: dupOffsets[0].fromText, + toText: toText, + }) + } else if len(dupOffsets) > 0 { + // Move non-dup to final output + mergedEdits = append(mergedEdits, dupOffsets[0]) } + dupOffsets = nil } - logf("Done.") + lastOffset := -1 + for _, fileEdit := range fileEdits { + if fileEdit.pos.Offset != lastOffset { + mergeFunc() + } + dupOffsets = append(dupOffsets, fileEdit) + lastOffset = fileEdit.pos.Offset + } + mergeFunc() + return mergedEdits +} + +// astFileIterator iterates over all files in an ast.Package. +type astFileIterator interface { + // Finds the position of a token. + Position(token.Pos) token.Position + // Reset resets the iterator. + Reset() + // Next returns the next filenameAstFilePair pair or nil if done. + Next() *filenameAstFilePair +} + +type filenameAstFilePair struct { + filename string + astFile *ast.File +} + +// realAstFileIterator implements astFileIterator. +type realAstFileIterator struct { + fset *token.FileSet + pkgs map[string]*ast.Package + ch chan *filenameAstFilePair + closed bool +} + +func (rafi *realAstFileIterator) Position(pos token.Pos) token.Position { + return rafi.fset.Position(pos) +} + +func (rafi *realAstFileIterator) Reset() { + if !rafi.closed && rafi.ch != nil { + logf("Closing old channel on Reset") + close(rafi.ch) + } + rafi.ch = make(chan *filenameAstFilePair, 10) + rafi.closed = false + + go func() { + var count int + for _, pkg := range rafi.pkgs { + for filename, f := range pkg.Files { + logf("Sending file #%v: %v to channel", count, filename) + rafi.ch <- &filenameAstFilePair{filename: filename, astFile: f} + count++ + } + } + rafi.closed = true + close(rafi.ch) + logf("Closed channel after sending %v files", count) + }() +} + +func (rafi *realAstFileIterator) Next() *filenameAstFilePair { + for pair := range rafi.ch { + logf("Next: returning file %v", pair.filename) + return pair + } + return nil +} + +func findAllServices(pkgs map[string]*ast.Package) servicesMap { + services := servicesMap{} + for _, pkg := range pkgs { + for filename, f := range pkg.Files { + if filename != "github.go" { + continue + } + + logf("Step 1 - Processing %v ...", filename) + if err := findClientServices(filename, f, services); err != nil { + log.Fatal(err) + } + } + } + return services +} + +func findAllServiceEndpoints(iter astFileIterator, services servicesMap) (endpointsMap, error) { + endpoints := endpointsMap{} + iter.Reset() + var errs []string // Collect all the errors and return in a big batch. + for next := iter.Next(); next != nil; next = iter.Next() { + filename, f := next.filename, next.astFile + if filename == "github.go" { + continue + } + + if *debugFile != "" && !strings.Contains(filename, *debugFile) { + continue + } + + logf("Step 2 - Processing %v ...", filename) + if err := processAST(filename, f, services, endpoints, iter); err != nil { + errs = append(errs, err.Error()) + } + } + + if len(errs) > 0 { + return nil, errors.New(strings.Join(errs, "\n")) + } + + return endpoints, nil +} + +func resolveHelpersAndCacheDocs(endpoints endpointsMap, docCache documentCacheWriter) (usedHelpers usedHelpersMap, endpointsByFilename endpointsByFilenameMap) { + usedHelpers = usedHelpersMap{} + endpointsByFilename = endpointsByFilenameMap{} + for k, v := range endpoints { + if _, ok := endpointsByFilename[v.filename]; !ok { + endpointsByFilename[v.filename] = []*Endpoint{} + } + endpointsByFilename[v.filename] = append(endpointsByFilename[v.filename], v) + + for _, cmt := range v.enterpriseRefLines { + docCache.CacheDocFromInternet(cmt.Text) + } + for _, cmt := range v.stdRefLines { + docCache.CacheDocFromInternet(cmt.Text) + } + + if v.httpMethod == "" && v.helperMethod != "" { + fullName := fmt.Sprintf("%v.%v", v.serviceName, v.helperMethod) + hm, ok := endpoints[fullName] + if !ok { + log.Fatalf("Unable to find helper method %q for %q", fullName, k) + } + if hm.httpMethod == "" { + log.Fatalf("Helper method %q for %q has empty httpMethod: %#v", fullName, k, hm) + } + v.httpMethod = hm.httpMethod + usedHelpers[fullName] = true + } + } + + return usedHelpers, endpointsByFilename +} + +type documentCacheReader interface { + UrlByMethodAndPath(string) (string, bool) +} + +type documentCacheWriter interface { + CacheDocFromInternet(urlWithFragmentID string) +} + +// documentCache implements documentCacheReader and documentCachWriter. +type documentCache struct { + apiDocs map[string]map[string][]*Endpoint // cached by URL, then mapped by web fragment identifier. + urlByMethodAndPath map[string]string +} + +func (dc *documentCache) UrlByMethodAndPath(methodAndPath string) (string, bool) { + url, ok := dc.urlByMethodAndPath[methodAndPath] + return url, ok +} + +func (dc *documentCache) CacheDocFromInternet(urlWithID string) { + if dc.apiDocs == nil { + dc.apiDocs = map[string]map[string][]*Endpoint{} // cached by URL, then mapped by web fragment identifier. + dc.urlByMethodAndPath = map[string]string{} + } + + url := getURL(urlWithID) + if _, ok := dc.apiDocs[url]; ok { + return // already cached + } + + // TODO: Enterprise URLs are currently causing problems - for example: + // GET https://developer.github.com/enterprise/v3/enterprise-admin/users/ + // returns StatusCode=404 + if strings.Contains(url, "enterprise") { + logf("Skipping troublesome Enterprise URL: %v", url) + return + } + + logf("GET %q ...", url) + resp, err := http.Get(url) + check("Unable to get URL: %v: %v", url, err) + if resp.StatusCode != http.StatusOK { + log.Fatalf("url %v - StatusCode=%v", url, resp.StatusCode) + } + + b, err := ioutil.ReadAll(resp.Body) + check("Unable to read body of URL: %v, %v", url, err) + check("Unable to close body of URL: %v, %v", url, resp.Body.Close()) + dc.apiDocs[url] = parseWebPageEndpoints(string(b)) + + // Now reverse-map the methods+paths to URLs. + for fragID, v := range dc.apiDocs[url] { + for _, endpoint := range v { + for _, path := range endpoint.urlFormats { + methodAndPath := fmt.Sprintf("%v %v", endpoint.httpMethod, path) + dc.urlByMethodAndPath[methodAndPath] = fmt.Sprintf("%v#%v", url, fragID) + logf("urlByMethodAndPath[%q] = %q", methodAndPath, dc.urlByMethodAndPath[methodAndPath]) + } + } + } } // FileEdit represents an edit that needs to be performed on a file. @@ -300,9 +578,14 @@ func getURL(s string) string { } j := strings.Index(s, "#") if j < i { - return s[i:] + s = s[i:] + } else { + s = s[i:j] } - return s[i:j] + if !strings.HasSuffix(s, "/") { // Prevent unnecessary redirects if possible. + s += "/" + } + return s } // Service represents a go-github service. @@ -321,18 +604,61 @@ type Endpoint struct { enterpriseRefLines []*ast.Comment stdRefLines []*ast.Comment + endpointComments []*ast.Comment +} + +// String helps with debugging by providing an easy-to-read summary of the endpoint. +func (e *Endpoint) String() string { + var b strings.Builder + b.WriteString(fmt.Sprintf(" filename: %v\n", e.filename)) + b.WriteString(fmt.Sprintf(" serviceName: %v\n", e.serviceName)) + b.WriteString(fmt.Sprintf(" endpointName: %v\n", e.endpointName)) + b.WriteString(fmt.Sprintf(" httpMethod: %v\n", e.httpMethod)) + if e.helperMethod != "" { + b.WriteString(fmt.Sprintf(" helperMethod: %v\n", e.helperMethod)) + } + for i := 0; i < len(e.urlFormats); i++ { + b.WriteString(fmt.Sprintf(" urlFormats[%v]: %v\n", i, e.urlFormats[i])) + } + for i := 0; i < len(e.enterpriseRefLines); i++ { + b.WriteString(fmt.Sprintf(" enterpriseRefLines[%v]: comment: %v\n", i, e.enterpriseRefLines[i].Text)) + } + for i := 0; i < len(e.stdRefLines); i++ { + b.WriteString(fmt.Sprintf(" stdRefLines[%v]: comment: %v\n", i, e.stdRefLines[i].Text)) + } + return b.String() } -func processAST(filename string, f *ast.File, services servicesMap, endpoints endpointsMap) error { +func (ep *Endpoint) checkHttpMethodOverride(path string) { + lookupOverride := fmt.Sprintf("%v.%v: %v %v", ep.serviceName, ep.endpointName, ep.httpMethod, path) + logf("Looking up override for %q", lookupOverride) + if v, ok := methodOverrides[lookupOverride]; ok { + logf("overriding method for %v to %q", lookupOverride, v) + ep.httpMethod = v + return + } +} + +func processAST(filename string, f *ast.File, services servicesMap, endpoints endpointsMap, iter astFileIterator) error { + var errs []string + for _, decl := range f.Decls { switch decl := decl.(type) { case *ast.FuncDecl: // Doc, Recv, Name, Type, Body if decl.Recv == nil || len(decl.Recv.List) != 1 || decl.Name == nil || decl.Body == nil { continue } + recv := decl.Recv.List[0] se, ok := recv.Type.(*ast.StarExpr) // Star, X if !ok || se.X == nil || len(recv.Names) != 1 { + if decl.Name.Name != "String" && decl.Name.Name != "Equal" && decl.Name.Name != "IsPullRequest" { + pos := iter.Position(recv.Pos()) + if id, ok := recv.Type.(*ast.Ident); ok { + pos = iter.Position(id.Pos()) + } + errs = append(errs, fmt.Sprintf("%v:%v:%v: method %v does not use a pointer receiver and needs fixing!", pos.Filename, pos.Line, pos.Column, decl.Name)) + } continue } recvType, ok := se.X.(*ast.Ident) // NamePos, Name, Obj @@ -362,7 +688,9 @@ func processAST(filename string, f *ast.File, services servicesMap, endpoints en logf("recvType = %#v", recvType) var enterpriseRefLines []*ast.Comment var stdRefLines []*ast.Comment + var endpointComments []*ast.Comment if decl.Doc != nil { + endpointComments = decl.Doc.List for i, comment := range decl.Doc.List { logf("doc.comment[%v] = %#v", i, *comment) if strings.Contains(comment.Text, enterpriseURL) { @@ -379,14 +707,6 @@ func processAST(filename string, f *ast.File, services servicesMap, endpoints en return fmt.Errorf("parseBody: %v", err) } - if len(bd.urlFormats) == 1 { - lookupOverride := fmt.Sprintf("%v.%v: %v %v", serviceName, endpointName, bd.httpMethod, bd.urlFormats[0]) - if v, ok := methodOverrides[lookupOverride]; ok { - logf("overriding method for %v to %q", lookupOverride, v) - bd.httpMethod = v - } - } - ep := &Endpoint{ endpointName: endpointName, filename: filename, @@ -396,7 +716,9 @@ func processAST(filename string, f *ast.File, services servicesMap, endpoints en helperMethod: bd.helperMethod, enterpriseRefLines: enterpriseRefLines, stdRefLines: stdRefLines, + endpointComments: endpointComments, } + // ep.checkHttpMethodOverride("") endpoints[fullName] = ep logf("endpoints[%q] = %#v", fullName, endpoints[fullName]) if ep.httpMethod == "" && (ep.helperMethod == "" || len(ep.urlFormats) == 0) { @@ -408,9 +730,9 @@ func processAST(filename string, f *ast.File, services servicesMap, endpoints en } } - // for _, comment := range f.Comments { - // log.Printf("Found %v comments, starting with: %#v", len(comment.List), comment.List[0]) - // } + if len(errs) > 0 { + return errors.New(strings.Join(errs, "\n")) + } return nil } @@ -564,7 +886,10 @@ func processAssignStmt(receiverName string, stmt *ast.AssignStmt) (httpMethod, u for i, expr := range stmt.Rhs { switch expr := expr.(type) { case *ast.BasicLit: // ValuePos, Kind, Value - assignments = append(assignments, lhsrhs{lhs: lhs[i], rhs: strings.Trim(expr.Value, `"`)}) + v := strings.Trim(expr.Value, `"`) + if !strings.HasPrefix(v, "?") { // Hack to remove "?recursive=1" + assignments = append(assignments, lhsrhs{lhs: lhs[i], rhs: v}) + } case *ast.BinaryExpr: logf("processAssignStmt: *ast.BinaryExpr: %#v", *expr) case *ast.CallExpr: // Fun, Lparen, Args, Ellipsis, Rparen @@ -782,7 +1107,13 @@ func parseWebPageEndpoints(buf string) map[string][]*Endpoint { if v := strings.Index(part, "<"); v > len(method) && v < eol { eol = v } + if v := strings.Index(part, "{"); v > len(method) && v < eol { + eol = v + } path := strings.TrimSpace(part[len(method):eol]) + if strings.HasPrefix(path, ":server") { // Hack to remove :server + path = strings.TrimPrefix(path, ":server") + } path = paramRE.ReplaceAllString(path, "%v") // strip leading garbage if i := strings.Index(path, "/"); i >= 0 { diff --git a/github/gen-doc-urls_test.go b/github/gen-doc-urls_test.go index 10d29a19a3a..d6939f12a89 100644 --- a/github/gen-doc-urls_test.go +++ b/github/gen-doc-urls_test.go @@ -4,3140 +4,558 @@ package main import ( + "fmt" + "go/parser" + "go/token" + "os" "reflect" + "regexp" + "strings" "testing" + + "github.com/pmezard/go-difflib/difflib" ) -func TestParseWebPageEndpoints(t *testing.T) { - got := parseWebPageEndpoints(testPage) +type pipelineSetup struct { + // Fields filled in by the unit test: + baseURL string + endpointsFromWebsite endpointsByFragmentID + filename string + serviceName string + originalGoSource string + wantGoSource string + wantNumEndpoints int + + // Fields filled in by setup: + docCache *fakeDocCache + fileRewriter *fakeFileRewriter + iter *fakeAstFileIterator + services servicesMap + wantFailure bool +} - for k := range got { - w, ok := want[k] - if !ok { - t.Errorf("got[%q] =\n%#v\nwant[%q] = nil", k, got[k], k) - continue - } - if len(got[k]) != len(w) { - t.Errorf("len(got[%q]) = %v, len(want[%q]) = %v", k, len(got[k]), k, len(w)) - continue - } - for i := 0; i < len(w); i++ { - if !reflect.DeepEqual(got[k][i], w[i]) { - t.Errorf("got[%q][%v] =\n%#v\nwant[%q][%v]:\n%#v", k, i, got[k][i], k, i, want[k][i]) +func (ps *pipelineSetup) setup(t *testing.T, stripURLs, destroyReceiverPointers bool) *pipelineSetup { + t.Helper() + + if stripURLs { + // For every GitHub API doc URL, remove it from the original source, + // and alternate between stripping the previous blank comment line and not. + for removeBlank := false; true; removeBlank = !removeBlank { + var changes bool + if removeBlank { + ps.originalGoSource, changes = removeNextURLAndOptionalBlank(ps.originalGoSource) + } else { + ps.originalGoSource, changes = removeNextURLLineOnly(ps.originalGoSource) + } + if !changes { + break } } + // log.Printf("Modified Go Source:\n%v", ps.originalGoSource) } - for k := range want { - if _, ok := got[k]; !ok { - t.Errorf("got[%q] = nil\nwant[%q]:\n%#v", k, k, want[k]) - } - } -} - -var want = map[string][]*Endpoint{ - "list-reactions-for-a-commit-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/comments/%v/reactions"}, httpMethod: "GET"}}, - - "delete-a-commit-comment-reaction": []*Endpoint{ - {urlFormats: []string{"repositories/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, - {urlFormats: []string{"repos/%v/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, - }, - - "create-reaction-for-an-issue": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/%v/reactions"}, httpMethod: "POST"}}, - - "delete-an-issue-reaction": []*Endpoint{ - {urlFormats: []string{"repositories/%v/issues/%v/reactions/%v"}, httpMethod: "DELETE"}, - {urlFormats: []string{"repos/%v/%v/issues/%v/reactions/%v"}, httpMethod: "DELETE"}, - }, - - "create-reaction-for-a-pull-request-review-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/pulls/comments/%v/reactions"}, httpMethod: "POST"}}, - - "list-reactions-for-a-team-discussion": []*Endpoint{ - {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/reactions"}, httpMethod: "GET"}, - {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/reactions"}, httpMethod: "GET"}, - }, - - "delete-a-reaction-legacy": []*Endpoint{{urlFormats: []string{"reactions/%v"}, httpMethod: "DELETE"}}, - - "list-reactions-for-a-team-discussion-comment-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "GET"}}, - - "delete-an-issue-comment-reaction": []*Endpoint{ - {urlFormats: []string{"repositories/%v/issues/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, - {urlFormats: []string{"repos/%v/%v/issues/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, - }, - - "list-reactions-for-a-pull-request-review-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/pulls/comments/%v/reactions"}, httpMethod: "GET"}}, - - "create-reaction-for-a-team-discussion-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/reactions"}, httpMethod: "POST"}}, - - "create-reaction-for-a-team-discussion-comment-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "POST"}}, - - "create-reaction-for-a-commit-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/comments/%v/reactions"}, httpMethod: "POST"}}, - - "list-reactions-for-an-issue": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/%v/reactions"}, httpMethod: "GET"}}, - - "create-reaction-for-an-issue-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/comments/%v/reactions"}, httpMethod: "POST"}}, - - "create-reaction-for-a-team-discussion": []*Endpoint{ - {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/reactions"}, httpMethod: "POST"}, - {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/reactions"}, httpMethod: "POST"}, - }, - - "delete-team-discussion-reaction": []*Endpoint{ - {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/reactions/%v"}, httpMethod: "DELETE"}, - {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/reactions/%v"}, httpMethod: "DELETE"}, - }, - "create-reaction-for-a-team-discussion-comment": []*Endpoint{ - {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "POST"}, - {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "POST"}, - }, - - "list-reactions-for-an-issue-comment": []*Endpoint{{urlFormats: []string{"repos/%v/%v/issues/comments/%v/reactions"}, httpMethod: "GET"}}, - - "delete-a-pull-request-comment-reaction": []*Endpoint{ - {urlFormats: []string{"repositories/%v/pulls/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, - {urlFormats: []string{"repos/%v/%v/pulls/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, - }, - - "list-reactions-for-a-team-discussion-comment": []*Endpoint{ - {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "GET"}, - {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/comments/%v/reactions"}, httpMethod: "GET"}, - }, + if destroyReceiverPointers { + from := fmt.Sprintf(" *%v) ", ps.serviceName) + to := fmt.Sprintf(" %v) ", ps.serviceName) + ps.originalGoSource = strings.ReplaceAll(ps.originalGoSource, from, to) + ps.wantFailure = true // receiver pointers must be fixed before running. + } - "delete-team-discussion-comment-reaction": []*Endpoint{ - {urlFormats: []string{"organizations/%v/team/%v/discussions/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, - {urlFormats: []string{"orgs/%v/teams/%v/discussions/%v/comments/%v/reactions/%v"}, httpMethod: "DELETE"}, - }, + ps.docCache = &fakeDocCache{ + t: t, + baseURL: ps.baseURL, + endpoints: ps.endpointsFromWebsite, + } + fset := token.NewFileSet() + ps.fileRewriter = &fakeFileRewriter{fset: fset, in: ps.originalGoSource} + ps.services = servicesMap{ps.serviceName: &Service{serviceName: ps.serviceName}} + astFile, err := parser.ParseFile(fset, ps.filename, ps.originalGoSource, parser.ParseComments) + if err != nil { + t.Fatalf("ParseFile: %v", err) + } + ps.iter = &fakeAstFileIterator{ + fset: fset, + orig: &filenameAstFilePair{ + filename: ps.filename, + astFile: astFile, + }, + } - "list-reactions-for-a-team-discussion-legacy": []*Endpoint{{urlFormats: []string{"teams/%v/discussions/%v/reactions"}, httpMethod: "GET"}}, + return ps } -var testPage = ` - - - - - - - - - Reactions | GitHub Developer Guide - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
-
-

- Reactions

- - - -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

- Reaction types

- -

When creating a reaction, the allowed values for the content parameter are as follows (with the - corresponding emoji for reference):

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
contentemoji
+1:+1:
-1:-1:
laugh:smile:
confused:confused:
heart:heart:
hooray:tada:
rocket:rocket:
eyes:eyes:
- -

- List reactions for a - commit comment -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

List the reactions to a commit comment.

- -
GET /repos/:owner/:repo/comments/:comment_id/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to - list all reactions to a commit comment.
- -

- Response

- -
Status: 200 OK
-Link: <https://api.github.com/resource?page=2>; rel="next",
-      <https://api.github.com/resource?page=5>; rel="last"
-
- - -
[
-  {
-    "id": 1,
-    "node_id": "MDg6UmVhY3Rpb24x",
-    "user": {
-      "login": "octocat",
-      "id": 1,
-      "node_id": "MDQ6VXNlcjE=",
-      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-      "gravatar_id": "",
-      "url": "https://api.github.com/users/octocat",
-      "html_url": "https://github.com/octocat",
-      "followers_url": "https://api.github.com/users/octocat/followers",
-      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-      "organizations_url": "https://api.github.com/users/octocat/orgs",
-      "repos_url": "https://api.github.com/users/octocat/repos",
-      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-      "received_events_url": "https://api.github.com/users/octocat/received_events",
-      "type": "User",
-      "site_admin": false
-    },
-    "content": "heart",
-    "created_at": "2016-05-20T20:09:31Z"
-  }
-]
-
- - -

- Create reaction for a - commit comment -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

Create a reaction to a commit comment. A response with a - Status: 200 OK means that you already added the reaction type to this commit comment.

- -
POST /repos/:owner/:repo/comments/:comment_id/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstring - Required. The reaction type to add to the - commit comment.
- -

- Example

- -
{
-  "content": "heart"
-}
-
- - -

- Response

- -
Status: 201 Created
-
- - -
{
-  "id": 1,
-  "node_id": "MDg6UmVhY3Rpb24x",
-  "user": {
-    "login": "octocat",
-    "id": 1,
-    "node_id": "MDQ6VXNlcjE=",
-    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-    "gravatar_id": "",
-    "url": "https://api.github.com/users/octocat",
-    "html_url": "https://github.com/octocat",
-    "followers_url": "https://api.github.com/users/octocat/followers",
-    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-    "organizations_url": "https://api.github.com/users/octocat/orgs",
-    "repos_url": "https://api.github.com/users/octocat/repos",
-    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-    "received_events_url": "https://api.github.com/users/octocat/received_events",
-    "type": "User",
-    "site_admin": false
-  },
-  "content": "heart",
-  "created_at": "2016-05-20T20:09:31Z"
-}
-
- - -

- Delete a commit comment - reaction -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -
- -

Note: You can also specify a repository by repository_id using the route - DELETE /repositories/:repository_id/comments/:comment_id/reactions/:reaction_id.

- -
- -

Delete a reaction to a commit comment.

- -
DELETE /repos/:owner/:repo/comments/:comment_id/reactions/:reaction_id
-
- -

- Response

- -
Status: 204 No Content
-
- - -

- List reactions for an - issue -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

List the reactions to an issue.

- -
GET /repos/:owner/:repo/issues/:issue_number/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to - list all reactions to an issue.
- -

- Response

- -
Status: 200 OK
-Link: <https://api.github.com/resource?page=2>; rel="next",
-      <https://api.github.com/resource?page=5>; rel="last"
-
- - -
[
-  {
-    "id": 1,
-    "node_id": "MDg6UmVhY3Rpb24x",
-    "user": {
-      "login": "octocat",
-      "id": 1,
-      "node_id": "MDQ6VXNlcjE=",
-      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-      "gravatar_id": "",
-      "url": "https://api.github.com/users/octocat",
-      "html_url": "https://github.com/octocat",
-      "followers_url": "https://api.github.com/users/octocat/followers",
-      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-      "organizations_url": "https://api.github.com/users/octocat/orgs",
-      "repos_url": "https://api.github.com/users/octocat/repos",
-      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-      "received_events_url": "https://api.github.com/users/octocat/received_events",
-      "type": "User",
-      "site_admin": false
-    },
-    "content": "heart",
-    "created_at": "2016-05-20T20:09:31Z"
-  }
-]
-
- - -

- Create reaction for an - issue

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

Create a reaction to an issue. A response with a Status: 200 OK means - that you already added the reaction type to this issue.

- -
POST /repos/:owner/:repo/issues/:issue_number/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstring - Required. The reaction type to add to the - issue.
- -

- Example

- -
{
-  "content": "heart"
-}
-
- - -

- Response

- -
Status: 201 Created
-
- - -
{
-  "id": 1,
-  "node_id": "MDg6UmVhY3Rpb24x",
-  "user": {
-    "login": "octocat",
-    "id": 1,
-    "node_id": "MDQ6VXNlcjE=",
-    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-    "gravatar_id": "",
-    "url": "https://api.github.com/users/octocat",
-    "html_url": "https://github.com/octocat",
-    "followers_url": "https://api.github.com/users/octocat/followers",
-    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-    "organizations_url": "https://api.github.com/users/octocat/orgs",
-    "repos_url": "https://api.github.com/users/octocat/repos",
-    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-    "received_events_url": "https://api.github.com/users/octocat/received_events",
-    "type": "User",
-    "site_admin": false
-  },
-  "content": "heart",
-  "created_at": "2016-05-20T20:09:31Z"
-}
-
+func (ps *pipelineSetup) validate(t *testing.T) { + t.Helper() + // Call pipeline + endpoints, err := findAllServiceEndpoints(ps.iter, ps.services) + if ps.wantFailure { + if err != nil { + // test successful - receivers must be pointers first + return + } + t.Fatalf("Expected non-pointer receivers to fail parsing, but no error was raised") + } + if err != nil { + t.Fatalf("Fail detected but not expected: %v", err) + } -

- Delete an issue reaction -

+ // log.Printf("endpoints=%#v (%v)", endpoints, len(endpoints)) + if len(endpoints) != ps.wantNumEndpoints { + t.Errorf("got %v endpoints, want %v", len(endpoints), ps.wantNumEndpoints) + } + usedHelpers, endpointsByFilename := resolveHelpersAndCacheDocs(endpoints, ps.docCache) + // log.Printf("endpointsByFilename=%#v (%v)", endpointsByFilename, len(endpointsByFilename[ps.filename])) + if len(endpointsByFilename[ps.filename]) != ps.wantNumEndpoints { + t.Errorf("got %v endpointsByFilename, want %v", len(endpointsByFilename[ps.filename]), ps.wantNumEndpoints) + } + validateRewriteURLs(usedHelpers, endpointsByFilename, ps.docCache, ps.fileRewriter) -
+ if ps.fileRewriter.out == "" { + t.Fatalf("No modifications were made to the file") + } -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

+ if ps.fileRewriter.out != ps.wantGoSource { + diff := difflib.ContextDiff{ + A: difflib.SplitLines(ps.fileRewriter.out), + B: difflib.SplitLines(ps.wantGoSource), + FromFile: "got", + ToFile: "want", + Context: 1, + Eol: "\n", + } + result, _ := difflib.GetContextDiffString(diff) + t.Errorf(strings.Replace(result, "\t", " ", -1)) + } +} -
  application/vnd.github.squirrel-girl-preview+json
-
+var ( + urlWithBlankCommentRE = regexp.MustCompile(`(//\n)?// GitHub API docs: [^\n]+\n`) + urlLineOnlyRE = regexp.MustCompile(`// GitHub API docs: [^\n]+\n`) +) -
+func removeNextURLAndOptionalBlank(s string) (string, bool) { + parts := urlWithBlankCommentRE.Split(s, 2) + if len(parts) == 1 { + return parts[0], false + } + return parts[0] + parts[1], true +} -
+func TestRemoveNextURLAndOptionalBlank(t *testing.T) { + tests := []struct { + name string + s string + want string + changes bool + }{ + {name: "empty string"}, + {name: "no URLs", s: "// line 1\n//\n// line 3", want: "// line 1\n//\n// line 3"}, + { + name: "URL without prior blank comment", + s: "// line 1\n// GitHub API docs: yeah\nfunc MyFunc() {\n", + want: "// line 1\nfunc MyFunc() {\n", + changes: true, + }, + { + name: "URL with prior blank comment", + s: "// line 1\n//\n// GitHub API docs: yeah\nfunc MyFunc() {\n", + want: "// line 1\nfunc MyFunc() {\n", + changes: true, + }, + } -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

+ for i, tt := range tests { + t.Run(fmt.Sprintf("test #%v: %v", i, tt.name), func(t *testing.T) { + got, changes := removeNextURLAndOptionalBlank(tt.s) + if got != tt.want { + t.Errorf("got = %v, want %v", got, tt.want) + } + if changes != tt.changes { + t.Errorf("got changes = %v, want %v", changes, tt.changes) + } + }) + } +} -
+func removeNextURLLineOnly(s string) (string, bool) { + parts := urlLineOnlyRE.Split(s, 2) + if len(parts) == 1 { + return parts[0], false + } + return parts[0] + parts[1], true +} -
+func TestRemoveNextURLLineOnly(t *testing.T) { + tests := []struct { + name string + s string + want string + changes bool + }{ + {name: "empty string"}, + {name: "no URLs", s: "// line 1\n//\n// line 3", want: "// line 1\n//\n// line 3"}, + { + name: "URL without prior blank comment", + s: "// line 1\n// GitHub API docs: yeah\nfunc MyFunc() {\n", + want: "// line 1\nfunc MyFunc() {\n", + changes: true, + }, + { + name: "URL with prior blank comment", + s: "// line 1\n//\n// GitHub API docs: yeah\nfunc MyFunc() {\n", + want: "// line 1\n//\nfunc MyFunc() {\n", + changes: true, + }, + } -

Note: You can also specify a repository by repository_id using the route - DELETE /repositories/:repository_id/issues/:issue_number/reactions/:reaction_id.

+ for i, tt := range tests { + t.Run(fmt.Sprintf("test #%v: %v", i, tt.name), func(t *testing.T) { + got, changes := removeNextURLLineOnly(tt.s) + if got != tt.want { + t.Errorf("got = %v, want %v", got, tt.want) + } + if changes != tt.changes { + t.Errorf("got changes = %v, want %v", changes, tt.changes) + } + }) + } +} -
+type endpointsByFragmentID map[string][]*Endpoint -

Delete a reaction to an issue.

+// fakeDocCache implements documentCacheReader and documentCacheWriter. +type fakeDocCache struct { + t *testing.T + baseURL string + endpoints endpointsByFragmentID +} -
DELETE /repos/:owner/:repo/issues/:issue_number/reactions/:reaction_id
-
+func (f *fakeDocCache) UrlByMethodAndPath(methodAndPath string) (string, bool) { + for fragmentID, endpoints := range f.endpoints { + for _, endpoint := range endpoints { + for _, urlFormat := range endpoint.urlFormats { + key := fmt.Sprintf("%v %v", endpoint.httpMethod, urlFormat) + if key == methodAndPath { + url := fmt.Sprintf("%v#%v", f.baseURL, fragmentID) + // log.Printf("UrlByMethodAndPath(%q) = (%q, true)", methodAndPath, url) + return url, true + } + } + } + } + f.t.Fatalf("fakeDocCache.UrlByMethodAndPath: unable to find method %v", methodAndPath) + return "", false +} -

- Response

+func (f *fakeDocCache) CacheDocFromInternet(url string) {} // no-op -
Status: 204 No Content
-
+// fakeFileRewriter implements FileRewriter. +type fakeFileRewriter struct { + fset *token.FileSet + in string + out string +} +func (f *fakeFileRewriter) Position(pos token.Pos) token.Position { + return f.fset.Position(pos) +} -

- List reactions for an - issue comment -

+func (f *fakeFileRewriter) ReadFile(filename string) ([]byte, error) { + return []byte(f.in), nil +} -
+func (f *fakeFileRewriter) WriteFile(filename string, buf []byte, mode os.FileMode) error { + f.out = string(buf) + return nil +} -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

+// fakeAstFileIterator implements astFileIterator. +type fakeAstFileIterator struct { + orig, next *filenameAstFilePair + fset *token.FileSet +} -
  application/vnd.github.squirrel-girl-preview+json
-
+func (f *fakeAstFileIterator) Position(pos token.Pos) token.Position { return f.fset.Position(pos) } +func (f *fakeAstFileIterator) Reset() { f.next = f.orig } +func (f *fakeAstFileIterator) Next() *filenameAstFilePair { + v := f.next + f.next = nil + return v +} -
+func TestSortAndMergeFileEdits(t *testing.T) { + tests := []struct { + name string + fileEdits []*FileEdit + want []*FileEdit + }{ + {name: "no edits"}, + { + name: "one edit", + fileEdits: []*FileEdit{ + {toText: "one edit"}, + }, + want: []*FileEdit{ + {toText: "one edit"}, + }, + }, + { + name: "two inserts at same offset - no extra blank comment", + fileEdits: []*FileEdit{ + {pos: token.Position{Offset: 2}, fromText: "", toText: "\n// one insert"}, + {pos: token.Position{Offset: 2}, fromText: "", toText: "\n// second insert"}, + }, + want: []*FileEdit{ + {pos: token.Position{Offset: 2}, toText: "\n// one insert\n// second insert"}, + }, + }, + { + name: "two inserts at same offset - strip extra blank comment", + fileEdits: []*FileEdit{ + {pos: token.Position{Offset: 2}, fromText: "", toText: "\n//\n// one insert"}, + {pos: token.Position{Offset: 2}, fromText: "", toText: "\n//\n// second insert"}, + }, + want: []*FileEdit{ + {pos: token.Position{Offset: 2}, toText: "\n//\n// one insert\n// second insert"}, + }, + }, + { + name: "two non-overlapping edits, low offset to high", + fileEdits: []*FileEdit{ + {fromText: ".", pos: token.Position{Offset: 0}, toText: "edit one"}, + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit two"}, + }, + want: []*FileEdit{ + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit two"}, + {fromText: ".", pos: token.Position{Offset: 0}, toText: "edit one"}, + }, + }, + { + name: "two non-overlapping edits, high offset to low", + fileEdits: []*FileEdit{ + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit two"}, + {fromText: ".", pos: token.Position{Offset: 0}, toText: "edit one"}, + }, + want: []*FileEdit{ + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit two"}, + {fromText: ".", pos: token.Position{Offset: 0}, toText: "edit one"}, + }, + }, + { + name: "two overlapping edits, text low to high", + fileEdits: []*FileEdit{ + {fromText: ".", toText: "edit 0"}, + {fromText: ".", toText: "edit 1"}, + }, + want: []*FileEdit{ + {fromText: ".", toText: "edit 0\nedit 1"}, + }, + }, + { + name: "two overlapping edits, text high to low", + fileEdits: []*FileEdit{ + {fromText: ".", toText: "edit 1"}, + {fromText: ".", toText: "edit 0"}, + }, + want: []*FileEdit{ + {fromText: ".", toText: "edit 0\nedit 1"}, + }, + }, + { + name: "dup, non-dup", + fileEdits: []*FileEdit{ + {fromText: ".", toText: "edit 1"}, + {fromText: ".", toText: "edit 0"}, + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 2"}, + }, + want: []*FileEdit{ + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 2"}, + {fromText: ".", toText: "edit 0\nedit 1"}, + }, + }, + { + name: "non-dup, dup", + fileEdits: []*FileEdit{ + {fromText: ".", toText: "edit 2"}, + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 1"}, + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 0"}, + }, + want: []*FileEdit{ + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 0\nedit 1"}, + {fromText: ".", toText: "edit 2"}, + }, + }, + { + name: "dup, non-dup, dup", + fileEdits: []*FileEdit{ + {fromText: ".", toText: "edit 1"}, + {fromText: ".", toText: "edit 0"}, + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 2"}, + {fromText: ".", pos: token.Position{Offset: 200}, toText: "edit 4"}, + {fromText: ".", pos: token.Position{Offset: 200}, toText: "edit 3"}, + }, + want: []*FileEdit{ + {fromText: ".", pos: token.Position{Offset: 200}, toText: "edit 3\nedit 4"}, + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 2"}, + {fromText: ".", toText: "edit 0\nedit 1"}, + }, + }, + { + name: "non-dup, dup, non-dup", + fileEdits: []*FileEdit{ + {fromText: ".", toText: "edit 2"}, + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 1"}, + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 0"}, + {fromText: ".", pos: token.Position{Offset: 200}, toText: "edit 3"}, + }, + want: []*FileEdit{ + {fromText: ".", pos: token.Position{Offset: 200}, toText: "edit 3"}, + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 0\nedit 1"}, + {fromText: ".", toText: "edit 2"}, + }, + }, + { + name: "triplet, non-dup", + fileEdits: []*FileEdit{ + {fromText: ".", toText: "edit 1"}, + {fromText: ".", toText: "edit 0"}, + {fromText: ".", toText: "edit 2"}, + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 3"}, + }, + want: []*FileEdit{ + {fromText: ".", pos: token.Position{Offset: 100}, toText: "edit 3"}, + {fromText: ".", toText: "edit 0\nedit 1\nedit 2"}, + }, + }, + } -
+ for i, tt := range tests { + t.Run(fmt.Sprintf("test #%v: %v", i, tt.name), func(t *testing.T) { + got := sortAndMergeFileEdits(tt.fileEdits) -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

+ if len(got) != len(tt.want) { + t.Errorf("len(got) = %v, len(want) = %v", len(got), len(tt.want)) + } + for i := 0; i < len(got); i++ { + var wantFileEdit *FileEdit + if i < len(tt.want) { + wantFileEdit = tt.want[i] + } + if !reflect.DeepEqual(got[i], wantFileEdit) { + t.Errorf("got[%v] =\n%#v\nwant[%v]:\n%#v", i, got[i], i, wantFileEdit) + } + } + }) + } +} -
+func TestPerformBufferEdits(t *testing.T) { + tests := []struct { + name string + fileEdits []*FileEdit + s string + want string + }{ + {name: "no edits", s: "my\nshort\nfile\n", want: "my\nshort\nfile\n"}, + { + name: "one edit", + fileEdits: []*FileEdit{ + {pos: token.Position{Offset: 3}, fromText: "short", toText: "one edit"}, + }, + s: "my\nshort\nfile\n", + want: "my\none edit\nfile\n", + }, + { + name: "one insert", + fileEdits: []*FileEdit{ + {pos: token.Position{Offset: 2}, fromText: "", toText: "\none insert"}, + }, + s: "my\nshort\nfile\n", + want: "my\none insert\nshort\nfile\n", + }, + { + name: "two inserts at same offset", + fileEdits: []*FileEdit{ + {pos: token.Position{Offset: 2}, fromText: "", toText: "\none insert"}, + {pos: token.Position{Offset: 2}, fromText: "", toText: "\nsecond insert"}, + }, + s: "my\nshort\nfile\n", + want: "my\none insert\nsecond insert\nshort\nfile\n", + }, + } -

List the reactions to an issue comment.

+ for i, tt := range tests { + t.Run(fmt.Sprintf("test #%v: %v", i, tt.name), func(t *testing.T) { + b := performBufferEdits([]byte(tt.s), tt.fileEdits) + got := string(b) -
GET /repos/:owner/:repo/issues/comments/:comment_id/reactions
-
+ if len(got) != len(tt.want) { + t.Errorf("len(got) = %v, len(want) = %v", len(got), len(tt.want)) + } + if got != tt.want { + t.Errorf("got = %v, want = %v", got, tt.want) + } + }) + } +} -

- Parameters

+func TestGitURL(t *testing.T) { + tests := []struct { + name string + s string + want string + }{ + {name: "empty string"}, + {name: "non-http", s: "howdy"}, + { + name: "normal URL, no slash", + s: "https://developer.github.com/v3/activity/events", + want: "https://developer.github.com/v3/activity/events/", + }, + { + name: "normal URL, with slash", + s: "https://developer.github.com/v3/activity/events/", + want: "https://developer.github.com/v3/activity/events/", + }, + { + name: "normal URL, with fragment identifier", + s: "https://developer.github.com/v3/activity/events/#list-public-events", + want: "https://developer.github.com/v3/activity/events/", + }, + } - - - - - - - - - - - - - - - -
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to - list all reactions to an issue comment.
+ for i, tt := range tests { + t.Run(fmt.Sprintf("test #%v: %v", i, tt.name), func(t *testing.T) { + got := getURL(tt.s) + if got != tt.want { + t.Errorf("getURL = %v ; want %v", got, tt.want) + } + }) + } +} -

- Response

+func testWebPageHelper(t *testing.T, got, want map[string][]*Endpoint) { + t.Helper() -
Status: 200 OK
-Link: <https://api.github.com/resource?page=2>; rel="next",
-      <https://api.github.com/resource?page=5>; rel="last"
-
- - -
[
-  {
-    "id": 1,
-    "node_id": "MDg6UmVhY3Rpb24x",
-    "user": {
-      "login": "octocat",
-      "id": 1,
-      "node_id": "MDQ6VXNlcjE=",
-      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-      "gravatar_id": "",
-      "url": "https://api.github.com/users/octocat",
-      "html_url": "https://github.com/octocat",
-      "followers_url": "https://api.github.com/users/octocat/followers",
-      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-      "organizations_url": "https://api.github.com/users/octocat/orgs",
-      "repos_url": "https://api.github.com/users/octocat/repos",
-      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-      "received_events_url": "https://api.github.com/users/octocat/received_events",
-      "type": "User",
-      "site_admin": false
-    },
-    "content": "heart",
-    "created_at": "2016-05-20T20:09:31Z"
-  }
-]
-
- - -

- Create reaction for an - issue comment -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

Create a reaction to an issue comment. A response with a - Status: 200 OK means that you already added the reaction type to this issue comment.

- -
POST /repos/:owner/:repo/issues/comments/:comment_id/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstring - Required. The reaction type to add to the - issue comment.
- -

- Example

- -
{
-  "content": "heart"
-}
-
- - -

- Response

- -
Status: 201 Created
-
- - -
{
-  "id": 1,
-  "node_id": "MDg6UmVhY3Rpb24x",
-  "user": {
-    "login": "octocat",
-    "id": 1,
-    "node_id": "MDQ6VXNlcjE=",
-    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-    "gravatar_id": "",
-    "url": "https://api.github.com/users/octocat",
-    "html_url": "https://github.com/octocat",
-    "followers_url": "https://api.github.com/users/octocat/followers",
-    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-    "organizations_url": "https://api.github.com/users/octocat/orgs",
-    "repos_url": "https://api.github.com/users/octocat/repos",
-    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-    "received_events_url": "https://api.github.com/users/octocat/received_events",
-    "type": "User",
-    "site_admin": false
-  },
-  "content": "heart",
-  "created_at": "2016-05-20T20:09:31Z"
-}
-
- - -

- Delete an issue comment - reaction -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -
- -

Note: You can also specify a repository by repository_id using the route - DELETE delete /repositories/:repository_id/issues/comments/:comment_id/reactions/:reaction_id. -

- -
- -

Delete a reaction to an issue comment.

- -
DELETE /repos/:owner/:repo/issues/comments/:comment_id/reactions/:reaction_id
-
- -

- Response

- -
Status: 204 No Content
-
- - -

- List reactions for a pull request review comment -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

List the reactions to a pull request review comment.

- -
GET /repos/:owner/:repo/pulls/comments/:comment_id/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to - list all reactions to a pull request review comment.
- -

- Response

- -
Status: 200 OK
-Link: <https://api.github.com/resource?page=2>; rel="next",
-      <https://api.github.com/resource?page=5>; rel="last"
-
- - -
[
-  {
-    "id": 1,
-    "node_id": "MDg6UmVhY3Rpb24x",
-    "user": {
-      "login": "octocat",
-      "id": 1,
-      "node_id": "MDQ6VXNlcjE=",
-      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-      "gravatar_id": "",
-      "url": "https://api.github.com/users/octocat",
-      "html_url": "https://github.com/octocat",
-      "followers_url": "https://api.github.com/users/octocat/followers",
-      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-      "organizations_url": "https://api.github.com/users/octocat/orgs",
-      "repos_url": "https://api.github.com/users/octocat/repos",
-      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-      "received_events_url": "https://api.github.com/users/octocat/received_events",
-      "type": "User",
-      "site_admin": false
-    },
-    "content": "heart",
-    "created_at": "2016-05-20T20:09:31Z"
-  }
-]
-
- - -

- Create reaction for a pull request review comment -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

Create a reaction to a pull request review comment. A response with a - Status: 200 OK means that you already added the reaction type to this pull request review - comment.

- -
POST /repos/:owner/:repo/pulls/comments/:comment_id/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstring - Required. The reaction type to add to the - pull request review comment.
- -

- Example

- -
{
-  "content": "heart"
-}
-
- - -

- Response

- -
Status: 201 Created
-
- - -
{
-  "id": 1,
-  "node_id": "MDg6UmVhY3Rpb24x",
-  "user": {
-    "login": "octocat",
-    "id": 1,
-    "node_id": "MDQ6VXNlcjE=",
-    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-    "gravatar_id": "",
-    "url": "https://api.github.com/users/octocat",
-    "html_url": "https://github.com/octocat",
-    "followers_url": "https://api.github.com/users/octocat/followers",
-    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-    "organizations_url": "https://api.github.com/users/octocat/orgs",
-    "repos_url": "https://api.github.com/users/octocat/repos",
-    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-    "received_events_url": "https://api.github.com/users/octocat/received_events",
-    "type": "User",
-    "site_admin": false
-  },
-  "content": "heart",
-  "created_at": "2016-05-20T20:09:31Z"
-}
-
- - -

- Delete a pull request - comment reaction -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -
- -

Note: You can also specify a repository by repository_id using the route - DELETE /repositories/:repository_id/pulls/comments/:comment_id/reactions/:reaction_id.

- -
- -

Delete a reaction to a pull request review comment.

- -
DELETE /repos/:owner/:repo/pulls/comments/:comment_id/reactions/:reaction_id
-
- -

- Response

- -
Status: 204 No Content
-
- - -

- List reactions for a - team discussion -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

List the reactions to a team discussion. OAuth access tokens require the - read:discussion scope.

- -
- -

Note: You can also specify a team by org_id and team_id using - the route GET /organizations/:org_id/team/:team_id/discussions/:discussion_number/reactions. -

- -
- -
GET /orgs/:org/teams/:team_slug/discussions/:discussion_number/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to - list all reactions to a team discussion.
- -

- Response

- -
Status: 200 OK
-Link: <https://api.github.com/resource?page=2>; rel="next",
-      <https://api.github.com/resource?page=5>; rel="last"
-
- - -
[
-  {
-    "id": 1,
-    "node_id": "MDg6UmVhY3Rpb24x",
-    "user": {
-      "login": "octocat",
-      "id": 1,
-      "node_id": "MDQ6VXNlcjE=",
-      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-      "gravatar_id": "",
-      "url": "https://api.github.com/users/octocat",
-      "html_url": "https://github.com/octocat",
-      "followers_url": "https://api.github.com/users/octocat/followers",
-      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-      "organizations_url": "https://api.github.com/users/octocat/orgs",
-      "repos_url": "https://api.github.com/users/octocat/repos",
-      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-      "received_events_url": "https://api.github.com/users/octocat/received_events",
-      "type": "User",
-      "site_admin": false
-    },
-    "content": "heart",
-    "created_at": "2016-05-20T20:09:31Z"
-  }
-]
-
- - -

- Create reaction for a - team discussion

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

Create a reaction to a team discussion. OAuth access tokens require the - write:discussion scope. A response with a - Status: 200 OK means that you already added the reaction type to this team discussion.

- -
- -

Note: You can also specify a team by org_id and team_id using - the route POST /organizations/:org_id/team/:team_id/discussions/:discussion_number/reactions. -

- -
- -
POST /orgs/:org/teams/:team_slug/discussions/:discussion_number/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstring - Required. The reaction type to add to the - team discussion.
- -

- Example

- -
{
-  "content": "heart"
-}
-
- - -

- Response

- -
Status: 201 Created
-
- - -
{
-  "id": 1,
-  "node_id": "MDg6UmVhY3Rpb24x",
-  "user": {
-    "login": "octocat",
-    "id": 1,
-    "node_id": "MDQ6VXNlcjE=",
-    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-    "gravatar_id": "",
-    "url": "https://api.github.com/users/octocat",
-    "html_url": "https://github.com/octocat",
-    "followers_url": "https://api.github.com/users/octocat/followers",
-    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-    "organizations_url": "https://api.github.com/users/octocat/orgs",
-    "repos_url": "https://api.github.com/users/octocat/repos",
-    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-    "received_events_url": "https://api.github.com/users/octocat/received_events",
-    "type": "User",
-    "site_admin": false
-  },
-  "content": "heart",
-  "created_at": "2016-05-20T20:09:31Z"
-}
-
- - -

- Delete team discussion - reaction -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -
- -

Note: You can also specify a team or organization with team_id and - org_id using the route - DELETE /organizations/:org_id/team/:team_id/discussions/:discussion_number/reactions/:reaction_id. -

- -
- -

Delete a reaction to a team discussion. OAuth access tokens require the - write:discussion scope.

- -
DELETE /orgs/:org/teams/:team_slug/discussions/:discussion_number/reactions/:reaction_id
-
- -

- Response

- -
Status: 204 No Content
-
- - -

- List reactions for a team discussion comment -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

List the reactions to a team discussion comment. OAuth access - tokens require the read:discussion scope.

- -
- -

Note: You can also specify a team by org_id and team_id using - the route - GET /organizations/:org_id/team/:team_id/discussions/:discussion_number/comments/:comment_number/reactions. -

- -
- -
GET /orgs/:org/teams/:team_slug/discussions/:discussion_number/comments/:comment_number/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to - list all reactions to a team discussion comment.
- -

- Response

- -
Status: 200 OK
-Link: <https://api.github.com/resource?page=2>; rel="next",
-      <https://api.github.com/resource?page=5>; rel="last"
-
- - -
[
-  {
-    "id": 1,
-    "node_id": "MDg6UmVhY3Rpb24x",
-    "user": {
-      "login": "octocat",
-      "id": 1,
-      "node_id": "MDQ6VXNlcjE=",
-      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-      "gravatar_id": "",
-      "url": "https://api.github.com/users/octocat",
-      "html_url": "https://github.com/octocat",
-      "followers_url": "https://api.github.com/users/octocat/followers",
-      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-      "organizations_url": "https://api.github.com/users/octocat/orgs",
-      "repos_url": "https://api.github.com/users/octocat/repos",
-      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-      "received_events_url": "https://api.github.com/users/octocat/received_events",
-      "type": "User",
-      "site_admin": false
-    },
-    "content": "heart",
-    "created_at": "2016-05-20T20:09:31Z"
-  }
-]
-
- - -

- Create reaction for a team discussion comment -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

Create a reaction to a team discussion comment. OAuth access - tokens require the write:discussion scope. A response with a - Status: 200 OK means that you already added the reaction type to this team discussion comment. -

- -
- -

Note: You can also specify a team by org_id and team_id using - the route - POST /organizations/:org_id/team/:team_id/discussions/:discussion_number/comments/:comment_number/reactions. -

- -
- -
POST /orgs/:org/teams/:team_slug/discussions/:discussion_number/comments/:comment_number/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstring - Required. The reaction type to add to the - team discussion comment.
- -

- Example

- -
{
-  "content": "heart"
-}
-
- - -

- Response

- -
Status: 201 Created
-
- - -
{
-  "id": 1,
-  "node_id": "MDg6UmVhY3Rpb24x",
-  "user": {
-    "login": "octocat",
-    "id": 1,
-    "node_id": "MDQ6VXNlcjE=",
-    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-    "gravatar_id": "",
-    "url": "https://api.github.com/users/octocat",
-    "html_url": "https://github.com/octocat",
-    "followers_url": "https://api.github.com/users/octocat/followers",
-    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-    "organizations_url": "https://api.github.com/users/octocat/orgs",
-    "repos_url": "https://api.github.com/users/octocat/repos",
-    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-    "received_events_url": "https://api.github.com/users/octocat/received_events",
-    "type": "User",
-    "site_admin": false
-  },
-  "content": "heart",
-  "created_at": "2016-05-20T20:09:31Z"
-}
-
- - -

- Delete team discussion - comment reaction -

- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -
- -

Note: You can also specify a team or organization with team_id and - org_id using the route - DELETE /organizations/:org_id/team/:team_id/discussions/:discussion_number/comments/:comment_number/reactions/:reaction_id. -

- -
- -

Delete a reaction to a team discussion comment. OAuth access - tokens require the write:discussion scope.

- -
DELETE /orgs/:org/teams/:team_slug/discussions/:discussion_number/comments/:comment_number/reactions/:reaction_id
-
- -

- Response

- -
Status: 204 No Content
-
- - -

- Delete a reaction (Legacy) -

- -
- -

Deprecation Notice: This endpoint route is deprecated and will be removed from the - Reactions API. We recommend migrating your existing code to use the new delete reactions endpoints. For more - information, see this blog post.

- -
- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

OAuth access tokens require the write:discussion scope, when deleting a team discussion or team - discussion comment.

- -
DELETE /reactions/:reaction_id
-
- -

- Response

- -
Status: 204 No Content
-
- - -

- List reactions for a team discussion (Legacy) -

- -
- -

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams - API. We recommend migrating your existing code to use the new List reactions for a team discussion - endpoint.

- -
- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

List the reactions to a team discussion. OAuth access tokens require the - read:discussion scope.

- -
GET /teams/:team_id/discussions/:discussion_number/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to - list all reactions to a team discussion.
- -

- Response

- -
Status: 200 OK
-Link: <https://api.github.com/resource?page=2>; rel="next",
-      <https://api.github.com/resource?page=5>; rel="last"
-
- - -
[
-  {
-    "id": 1,
-    "node_id": "MDg6UmVhY3Rpb24x",
-    "user": {
-      "login": "octocat",
-      "id": 1,
-      "node_id": "MDQ6VXNlcjE=",
-      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-      "gravatar_id": "",
-      "url": "https://api.github.com/users/octocat",
-      "html_url": "https://github.com/octocat",
-      "followers_url": "https://api.github.com/users/octocat/followers",
-      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-      "organizations_url": "https://api.github.com/users/octocat/orgs",
-      "repos_url": "https://api.github.com/users/octocat/repos",
-      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-      "received_events_url": "https://api.github.com/users/octocat/received_events",
-      "type": "User",
-      "site_admin": false
-    },
-    "content": "heart",
-    "created_at": "2016-05-20T20:09:31Z"
-  }
-]
-
- - -

- Create reaction for a team discussion (Legacy)

- -
- -

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams - API. We recommend migrating your existing code to use the new Create reaction for a team discussion - endpoint.

- -
- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

Create a reaction to a team discussion. OAuth access tokens require the - write:discussion scope. A response with a - Status: 200 OK means that you already added the reaction type to this team discussion.

- -
POST /teams/:team_id/discussions/:discussion_number/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstring - Required. The reaction type to add to the - team discussion.
- -

- Example

- -
{
-  "content": "heart"
-}
-
- - -

- Response

- -
Status: 201 Created
-
- - -
{
-  "id": 1,
-  "node_id": "MDg6UmVhY3Rpb24x",
-  "user": {
-    "login": "octocat",
-    "id": 1,
-    "node_id": "MDQ6VXNlcjE=",
-    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-    "gravatar_id": "",
-    "url": "https://api.github.com/users/octocat",
-    "html_url": "https://github.com/octocat",
-    "followers_url": "https://api.github.com/users/octocat/followers",
-    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-    "organizations_url": "https://api.github.com/users/octocat/orgs",
-    "repos_url": "https://api.github.com/users/octocat/repos",
-    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-    "received_events_url": "https://api.github.com/users/octocat/received_events",
-    "type": "User",
-    "site_admin": false
-  },
-  "content": "heart",
-  "created_at": "2016-05-20T20:09:31Z"
-}
-
- - -

- List reactions for a team discussion comment (Legacy) -

- -
- -

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams - API. We recommend migrating your existing code to use the new List reactions for a team discussion comment - endpoint.

- -
- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

List the reactions to a team discussion comment. OAuth access - tokens require the read:discussion scope.

- -
GET /teams/:team_id/discussions/:discussion_number/comments/:comment_number/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstringReturns a single reaction type. Omit this parameter to - list all reactions to a team discussion comment.
- -

- Response

- -
Status: 200 OK
-Link: <https://api.github.com/resource?page=2>; rel="next",
-      <https://api.github.com/resource?page=5>; rel="last"
-
- - -
[
-  {
-    "id": 1,
-    "node_id": "MDg6UmVhY3Rpb24x",
-    "user": {
-      "login": "octocat",
-      "id": 1,
-      "node_id": "MDQ6VXNlcjE=",
-      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-      "gravatar_id": "",
-      "url": "https://api.github.com/users/octocat",
-      "html_url": "https://github.com/octocat",
-      "followers_url": "https://api.github.com/users/octocat/followers",
-      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-      "organizations_url": "https://api.github.com/users/octocat/orgs",
-      "repos_url": "https://api.github.com/users/octocat/repos",
-      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-      "received_events_url": "https://api.github.com/users/octocat/received_events",
-      "type": "User",
-      "site_admin": false
-    },
-    "content": "heart",
-    "created_at": "2016-05-20T20:09:31Z"
-  }
-]
-
- - -

- Create reaction for a team discussion comment (Legacy) -

- -
- -

Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams - API. We recommend migrating your existing code to use the new Create reaction for a team discussion comment - endpoint.

- -
- -
- -

Note: APIs for managing reactions are currently available for developers to preview. See - the blog post for full details. To access the API - during the preview period, you must provide a custom media type in the - Accept header:

- -
  application/vnd.github.squirrel-girl-preview+json
-
- -
- -
- -

Warning: The API may change without advance notice during the preview period. Preview - features are not supported for production use. If you experience any issues, contact GitHub Support or GitHub - Premium Support.

- -
- -

Create a reaction to a team discussion comment. OAuth access - tokens require the write:discussion scope. A response with a - Status: 200 OK means that you already added the reaction type to this team discussion comment. -

- -
POST /teams/:team_id/discussions/:discussion_number/comments/:comment_number/reactions
-
- -

- Parameters

- - - - - - - - - - - - - - - - -
NameTypeDescription
contentstring - Required. The reaction type to add to the - team discussion comment.
- -

- Example

- -
{
-  "content": "heart"
-}
-
- - -

- Response

- -
Status: 201 Created
-
- - -
{
-  "id": 1,
-  "node_id": "MDg6UmVhY3Rpb24x",
-  "user": {
-    "login": "octocat",
-    "id": 1,
-    "node_id": "MDQ6VXNlcjE=",
-    "avatar_url": "https://github.com/images/error/octocat_happy.gif",
-    "gravatar_id": "",
-    "url": "https://api.github.com/users/octocat",
-    "html_url": "https://github.com/octocat",
-    "followers_url": "https://api.github.com/users/octocat/followers",
-    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
-    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
-    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
-    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
-    "organizations_url": "https://api.github.com/users/octocat/orgs",
-    "repos_url": "https://api.github.com/users/octocat/repos",
-    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
-    "received_events_url": "https://api.github.com/users/octocat/received_events",
-    "type": "User",
-    "site_admin": false
-  },
-  "content": "heart",
-  "created_at": "2016-05-20T20:09:31Z"
-}
-
- -
- - - - - -
-
- - - - - - - - -` + for k := range got { + w, ok := want[k] + if len(got[k]) != len(w) { + t.Errorf("len(got[%q]) = %v, len(want[%q]) = %v", k, len(got[k]), k, len(w)) + } + for i := 0; i < len(got[k]); i++ { + var wantEndpoint *Endpoint + if ok && i < len(w) { + wantEndpoint = w[i] + } + if !reflect.DeepEqual(got[k][i], wantEndpoint) { + t.Errorf("got[%q][%v] =\n%#v\nwant[%q][%v]:\n%#v", k, i, got[k][i], k, i, wantEndpoint) + } + } + } + for k := range want { + if _, ok := got[k]; !ok { + t.Errorf("got[%q] = nil\nwant[%q]:\n%#v", k, k, want[k]) + } + } +} diff --git a/github/gists.go b/github/gists.go index 915ee381812..d7fb5217795 100644 --- a/github/gists.go +++ b/github/gists.go @@ -96,7 +96,7 @@ type GistListOptions struct { // is authenticated, it will returns all gists for the authenticated // user. // -// GitHub API docs: https://developer.github.com/v3/gists/#list-gists-for-the-authenticated-user-for-a-user +// 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 if user != "" { diff --git a/github/git_refs.go b/github/git_refs.go index a6269e5a9e4..0b29d838765 100644 --- a/github/git_refs.go +++ b/github/git_refs.go @@ -55,10 +55,10 @@ type updateRefRequest struct { // 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-single-reference func (s *GitService) GetRef(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, refURLEscape(ref)) + u := fmt.Sprintf("repos/%v/%v/git/ref/%v", owner, repo, refURLEscape(ref)) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err diff --git a/github/gitignore.go b/github/gitignore.go index 2f691bc323e..dc2eab757ae 100644 --- a/github/gitignore.go +++ b/github/gitignore.go @@ -29,7 +29,7 @@ func (g Gitignore) String() string { // List all available Gitignore 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) if err != nil { return nil, nil, err @@ -47,7 +47,7 @@ func (s GitignoresService) List(ctx context.Context) ([]string, *Response, error // Get a Gitignore by name. // // GitHub API docs: https://developer.github.com/v3/gitignore/#get-a-single-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) req, err := s.client.NewRequest("GET", u, nil) if err != nil { diff --git a/github/issues.go b/github/issues.go index 8c2f47ea686..ae6b9e2420a 100644 --- a/github/issues.go +++ b/github/issues.go @@ -129,7 +129,7 @@ type PullRequestLinks struct { // organization repositories; if false, list only owned and member // repositories. // -// GitHub API docs: https://developer.github.com/v3/issues/#list-user-account-issues-assigned-to-the-authenticated-user-assigned-to-the-authenticated-user +// 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 if all { diff --git a/github/migrations_source_import.go b/github/migrations_source_import.go index cbdf1ea8a13..3980dc902c1 100644 --- a/github/migrations_source_import.go +++ b/github/migrations_source_import.go @@ -146,7 +146,7 @@ func (f LargeFile) String() string { // 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) { u := fmt.Sprintf("repos/%v/%v/import", owner, repo) req, err := s.client.NewRequest("PUT", u, in) @@ -165,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. // -// 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-import-progress func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo string) (*Import, *Response, error) { u := fmt.Sprintf("repos/%v/%v/import", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -184,7 +184,7 @@ func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo strin // 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-existing-import func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { u := fmt.Sprintf("repos/%v/%v/import", owner, repo) req, err := s.client.NewRequest("PATCH", u, in) @@ -213,7 +213,7 @@ func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, // This method and MapCommitAuthor allow you to provide correct Git author // 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) { u := fmt.Sprintf("repos/%v/%v/import/authors", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -234,7 +234,7 @@ func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string // application can continue updating authors any time before you push new // 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) { u := fmt.Sprintf("repos/%v/%v/import/authors/%v", owner, repo, id) req, err := s.client.NewRequest("PATCH", u, author) @@ -255,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 // 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/#set-git-lfs-preference 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) req, err := s.client.NewRequest("PATCH", u, in) @@ -274,7 +274,7 @@ func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo str // 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) { u := fmt.Sprintf("repos/%v/%v/import/large_files", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -293,7 +293,7 @@ func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ( // 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) { u := fmt.Sprintf("repos/%v/%v/import", owner, repo) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/github/orgs_members.go b/github/orgs_members.go index e701be6dbd2..a2f8892418d 100644 --- a/github/orgs_members.go +++ b/github/orgs_members.go @@ -206,9 +206,8 @@ func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opts *Lis // Passing an empty string for user will get the membership for the // authenticated user. // -// GitHub API docs: -// https://developer.github.com/v3/orgs/members/#get-organization-membership -// https://developer.github.com/v3/orgs/members/#get-your-organization-membership +// GitHub API docs: https://developer.github.com/v3/orgs/members/#get-your-organization-membership +// GitHub API docs: https://developer.github.com/v3/orgs/members/#get-organization-membership func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org string) (*Membership, *Response, error) { var u string if user != "" { diff --git a/github/pulls.go b/github/pulls.go index 349c79e6b2b..019432659a2 100644 --- a/github/pulls.go +++ b/github/pulls.go @@ -214,6 +214,8 @@ func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string } // GetRaw gets a single pull request in raw (diff or patch) format. +// +// GitHub API docs: https://developer.github.com/v3/pulls/#get-a-single-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) req, err := s.client.NewRequest("GET", u, nil) diff --git a/github/reactions.go b/github/reactions.go index 6c72fec52fa..ce0a7518295 100644 --- a/github/reactions.go +++ b/github/reactions.go @@ -89,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". // // 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) body := &Reaction{Content: String(content)} @@ -161,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". // // 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) body := &Reaction{Content: String(content)} @@ -233,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". // // 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) body := &Reaction{Content: String(content)} @@ -304,8 +304,8 @@ func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, // 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". // -// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment -func (s ReactionsService) CreatePullRequestCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { +// 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) { u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) body := &Reaction{Content: String(content)} diff --git a/github/repos.go b/github/repos.go index c7f09d40a91..0db3e309035 100644 --- a/github/repos.go +++ b/github/repos.go @@ -182,7 +182,7 @@ type RepositoryListOptions struct { // List the repositories for a user. Passing the empty string will list // repositories for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/repos/#list-repositories-for-the-authenticated-usera-user +// 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 if user != "" { @@ -326,7 +326,7 @@ type createRepoRequest struct { // Note that only a subset of the repo fields are used and repo must // not be nil. // -// GitHub API docs: https://developer.github.com/v3/repos/#create-a-repository-for-the-authenticated-user-an-organization-repository +// GitHub API docs: https://developer.github.com/v3/repos/#create-a-repository-for-the-authenticated-user func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { var u string if org != "" { diff --git a/github/repos_commits.go b/github/repos_commits.go index 59a2322b6b5..4db577085ad 100644 --- a/github/repos_commits.go +++ b/github/repos_commits.go @@ -167,6 +167,8 @@ func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha st } // GetCommitRaw fetches the specified commit in raw (diff or patch) format. +// +// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-single-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) req, err := s.client.NewRequest("GET", u, nil) diff --git a/github/repos_keys.go b/github/repos_keys.go index e389504e660..0eefd3dd96f 100644 --- a/github/repos_keys.go +++ b/github/repos_keys.go @@ -76,26 +76,6 @@ func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo 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. // // GitHub API docs: https://developer.github.com/v3/repos/keys/#remove-a-deploy-key diff --git a/github/users.go b/github/users.go index 8b6ce5d87b9..97747f713c6 100644 --- a/github/users.go +++ b/github/users.go @@ -78,7 +78,7 @@ func (u User) String() string { // user. // // GitHub API docs: https://developer.github.com/v3/users/#get-a-single-user -// and: https://developer.github.com/v3/users/#get-the-authenticated-user +// GitHub API docs: https://developer.github.com/v3/users/#get-the-authenticated-user func (s *UsersService) Get(ctx context.Context, user string) (*User, *Response, error) { var u string if user != "" { diff --git a/github/users_projects.go b/github/users_projects.go index 64e85a03226..1357055040c 100644 --- a/github/users_projects.go +++ b/github/users_projects.go @@ -49,7 +49,7 @@ type CreateUserProjectOptions struct { // // GitHub API docs: https://developer.github.com/v3/projects/#create-a-user-project func (s *UsersService) CreateProject(ctx context.Context, opts *CreateUserProjectOptions) (*Project, *Response, error) { - u := "users/projects" + u := "user/projects" req, err := s.client.NewRequest("POST", u, opts) if err != nil { return nil, nil, err diff --git a/go.mod b/go.mod index 6cf63d146dc..880f5ca96a3 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/google/go-github/v30 require ( github.com/golang/protobuf v1.3.2 // indirect github.com/google/go-querystring v1.0.0 + github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/net v0.0.0-20190311183353-d8887717615a // indirect golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be diff --git a/go.sum b/go.sum index dbab13e8b82..02d8bb7c9de 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= From 150ad19247563ec5975d1e9f69b8a208fd52d950 Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Sun, 29 Mar 2020 22:36:34 -0400 Subject: [PATCH 03/12] Ignore bash scripts --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3515c4b9740..d99e2ea721c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +*.sh *.test coverage.out From ac6d615cc36dc79e816ab89e91ba318aa519de4a Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Sun, 29 Mar 2020 22:47:15 -0400 Subject: [PATCH 04/12] Revert git_refs changes --- github/activity_star.go | 2 +- github/activity_watching.go | 2 +- github/apps.go | 2 +- github/apps_marketplace.go | 2 +- github/gen-doc-urls.go | 1 + github/gists.go | 2 +- github/git_refs.go | 4 ++-- github/github.go | 1 + github/issues.go | 2 +- github/issues_comments.go | 2 +- github/orgs.go | 2 +- github/orgs_members.go | 2 +- github/pulls_comments.go | 2 +- github/repos.go | 4 ++-- github/repos_keys_test.go | 37 ----------------------------------- github/users_followers.go | 6 +++--- github/users_gpg_keys.go | 2 +- github/users_keys.go | 2 +- github/users_projects_test.go | 2 +- 19 files changed, 22 insertions(+), 57 deletions(-) diff --git a/github/activity_star.go b/github/activity_star.go index 4845adcabcd..921c6578304 100644 --- a/github/activity_star.go +++ b/github/activity_star.go @@ -67,7 +67,7 @@ type ActivityListStarredOptions struct { // ListStarred lists all the repos starred by a user. Passing the empty string // will list the starred repositories for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-repositories-starred-by-the-authenticated-user +// 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, opts *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) { var u string if user != "" { diff --git a/github/activity_watching.go b/github/activity_watching.go index 09036fdf68c..cca07352db8 100644 --- a/github/activity_watching.go +++ b/github/activity_watching.go @@ -52,7 +52,7 @@ func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, // ListWatched lists the repositories the specified user is watching. Passing // the empty string will fetch watched repos for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-watched-by-the-authenticated-user +// 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, opts *ListOptions) ([]*Repository, *Response, error) { var u string if user != "" { diff --git a/github/apps.go b/github/apps.go index 9ffcfc45310..ee57b9eeb30 100644 --- a/github/apps.go +++ b/github/apps.go @@ -123,7 +123,7 @@ func (i Installation) String() string { // 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-github-app +// 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 != "" { diff --git a/github/apps_marketplace.go b/github/apps_marketplace.go index 898ad62eba5..e12617aafe5 100644 --- a/github/apps_marketplace.go +++ b/github/apps_marketplace.go @@ -150,7 +150,7 @@ func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, acc // ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user. // -// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-subscriptions-for-the-authenticated-user-stubbed +// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-subscriptions-for-the-authenticated-user func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opts *ListOptions) ([]*MarketplacePurchase, *Response, error) { uri := "user/marketplace_purchases" if s.Stubbed { diff --git a/github/gen-doc-urls.go b/github/gen-doc-urls.go index 6d223f45348..471e8ac8241 100644 --- a/github/gen-doc-urls.go +++ b/github/gen-doc-urls.go @@ -59,6 +59,7 @@ var ( "AppsService.FindRepositoryInstallationByID": true, "AuthorizationsService.CreateImpersonation": true, "AuthorizationsService.DeleteImpersonation": true, + "GitService.GetRef": true, "GitService.GetRefs": true, "GitService.ListRefs": true, "MarketplaceService.marketplaceURI": true, diff --git a/github/gists.go b/github/gists.go index d7fb5217795..244dfe09810 100644 --- a/github/gists.go +++ b/github/gists.go @@ -96,7 +96,7 @@ type GistListOptions struct { // is authenticated, it will returns all gists for the authenticated // user. // -// GitHub API docs: https://developer.github.com/v3/gists/#list-gists-for-the-authenticated-user +// GitHub API docs: https://developer.github.com/v3/gists/#list-gists-for-a-user func (s *GistsService) List(ctx context.Context, user string, opts *GistListOptions) ([]*Gist, *Response, error) { var u string if user != "" { diff --git a/github/git_refs.go b/github/git_refs.go index 0b29d838765..a6269e5a9e4 100644 --- a/github/git_refs.go +++ b/github/git_refs.go @@ -55,10 +55,10 @@ type updateRefRequest struct { // 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-single-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) { ref = strings.TrimPrefix(ref, "refs/") - u := fmt.Sprintf("repos/%v/%v/git/ref/%v", owner, repo, refURLEscape(ref)) + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(ref)) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err diff --git a/github/github.go b/github/github.go index 94f31a4c261..d71ca337f33 100644 --- a/github/github.go +++ b/github/github.go @@ -5,6 +5,7 @@ //go:generate go run gen-accessors.go //go:generate go run gen-stringify-test.go +//go:generate go run gen-doc-urls.go package github diff --git a/github/issues.go b/github/issues.go index ae6b9e2420a..e5bfb02a504 100644 --- a/github/issues.go +++ b/github/issues.go @@ -129,7 +129,7 @@ type PullRequestLinks struct { // organization repositories; if false, list only owned and member // repositories. // -// GitHub API docs: https://developer.github.com/v3/issues/#list-user-account-issues-assigned-to-the-authenticated-user +// 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, opts *IssueListOptions) ([]*Issue, *Response, error) { var u string if all { diff --git a/github/issues_comments.go b/github/issues_comments.go index b56f5d4d649..56b24c19179 100644 --- a/github/issues_comments.go +++ b/github/issues_comments.go @@ -50,7 +50,7 @@ type IssueListCommentsOptions struct { // ListComments lists all comments on the specified issue. Specifying an issue // 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-in-a-repository +// GitHub API docs: https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opts *IssueListCommentsOptions) ([]*IssueComment, *Response, error) { var u string if number == 0 { diff --git a/github/orgs.go b/github/orgs.go index d0631495062..63fa8538c74 100644 --- a/github/orgs.go +++ b/github/orgs.go @@ -144,7 +144,7 @@ func (s *OrganizationsService) ListAll(ctx context.Context, opts *OrganizationsL // List the organizations for a user. Passing the empty string will list // organizations for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/orgs/#oauth-scope-requirements +// GitHub API docs: https://developer.github.com/v3/orgs/#list-user-organizations func (s *OrganizationsService) List(ctx context.Context, user string, opts *ListOptions) ([]*Organization, *Response, error) { var u string if user != "" { diff --git a/github/orgs_members.go b/github/orgs_members.go index a2f8892418d..aa282a112ed 100644 --- a/github/orgs_members.go +++ b/github/orgs_members.go @@ -71,7 +71,7 @@ type ListMembersOptions struct { // user is an owner of the organization, this will return both concealed and // public members, otherwise it will only return public members. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#public-members-list +// GitHub API docs: https://developer.github.com/v3/orgs/members/#members-list func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opts *ListMembersOptions) ([]*User, *Response, error) { var u string if opts != nil && opts.PublicOnly { diff --git a/github/pulls_comments.go b/github/pulls_comments.go index 230adcc4c72..b5423cd3270 100644 --- a/github/pulls_comments.go +++ b/github/pulls_comments.go @@ -66,7 +66,7 @@ type PullRequestListCommentsOptions struct { // pull request number of 0 will return all comments on all pull requests for // the repository. // -// GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-comments-in-a-repository +// GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request func (s *PullRequestsService) ListComments(ctx context.Context, owner string, repo string, number int, opts *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) { var u string if number == 0 { diff --git a/github/repos.go b/github/repos.go index 0db3e309035..acaf92b0ec9 100644 --- a/github/repos.go +++ b/github/repos.go @@ -182,7 +182,7 @@ type RepositoryListOptions struct { // List the repositories for a user. Passing the empty string will list // repositories for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/repos/#list-repositories-for-the-authenticated-user +// GitHub API docs: https://developer.github.com/v3/repos/#list-repositories-for-a-user func (s *RepositoriesService) List(ctx context.Context, user string, opts *RepositoryListOptions) ([]*Repository, *Response, error) { var u string if user != "" { @@ -326,7 +326,7 @@ type createRepoRequest struct { // Note that only a subset of the repo fields are used and repo must // not be nil. // -// 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) { var u string if org != "" { diff --git a/github/repos_keys_test.go b/github/repos_keys_test.go index 75a17356edd..7a9a4b09f7b 100644 --- a/github/repos_keys_test.go +++ b/github/repos_keys_test.go @@ -109,43 +109,6 @@ func TestRepositoriesService_CreateKey_invalidOwner(t *testing.T) { testURLParseError(t, err) } -func TestRepositoriesService_EditKey(t *testing.T) { - client, mux, _, teardown := setup() - defer teardown() - - input := &Key{Key: String("k"), Title: String("t")} - - mux.HandleFunc("/repos/o/r/keys/1", func(w http.ResponseWriter, r *http.Request) { - v := new(Key) - json.NewDecoder(r.Body).Decode(v) - - testMethod(t, r, "PATCH") - if !reflect.DeepEqual(v, input) { - t.Errorf("Request body = %+v, want %+v", v, input) - } - - fmt.Fprint(w, `{"id":1}`) - }) - - key, _, err := client.Repositories.EditKey(context.Background(), "o", "r", 1, input) - if err != nil { - t.Errorf("Repositories.EditKey returned error: %v", err) - } - - want := &Key{ID: Int64(1)} - if !reflect.DeepEqual(key, want) { - t.Errorf("Repositories.EditKey returned %+v, want %+v", key, want) - } -} - -func TestRepositoriesService_EditKey_invalidOwner(t *testing.T) { - client, _, _, teardown := setup() - defer teardown() - - _, _, err := client.Repositories.EditKey(context.Background(), "%", "%", 1, nil) - testURLParseError(t, err) -} - func TestRepositoriesService_DeleteKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() diff --git a/github/users_followers.go b/github/users_followers.go index afa7d4b6b71..a429a1b2a3d 100644 --- a/github/users_followers.go +++ b/github/users_followers.go @@ -13,7 +13,7 @@ import ( // ListFollowers lists the followers for a user. Passing the empty string will // fetch followers for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/followers/#list-followers-of-a-user +// GitHub API docs: https://developer.github.com/v3/users/followers/#list-followers-of-the-authenticated-user func (s *UsersService) ListFollowers(ctx context.Context, user string, opts *ListOptions) ([]*User, *Response, error) { var u string if user != "" { @@ -43,7 +43,7 @@ func (s *UsersService) ListFollowers(ctx context.Context, user string, opts *Lis // ListFollowing lists the people that a user is following. Passing the empty // string will list people the authenticated user is following. // -// GitHub API docs: https://developer.github.com/v3/users/followers/#list-users-followed-by-another-user +// GitHub API docs: https://developer.github.com/v3/users/followers/#list-users-followed-by-the-authenticated-user func (s *UsersService) ListFollowing(ctx context.Context, user string, opts *ListOptions) ([]*User, *Response, error) { var u string if user != "" { @@ -73,7 +73,7 @@ func (s *UsersService) ListFollowing(ctx context.Context, user string, opts *Lis // IsFollowing checks if "user" is following "target". Passing the empty // string for "user" will check if the authenticated user is following "target". // -// GitHub API docs: https://developer.github.com/v3/users/followers/#check-if-you-are-following-a-user +// GitHub API docs: https://developer.github.com/v3/users/followers/#check-if-one-user-follows-another func (s *UsersService) IsFollowing(ctx context.Context, user, target string) (bool, *Response, error) { var u string if user != "" { diff --git a/github/users_gpg_keys.go b/github/users_gpg_keys.go index 68bdcf87c85..1d4dab045af 100644 --- a/github/users_gpg_keys.go +++ b/github/users_gpg_keys.go @@ -44,7 +44,7 @@ type GPGEmail struct { // string will fetch keys for the authenticated user. It requires authentication // via Basic Auth or via OAuth with at least read:gpg_key scope. // -// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#list-your-gpg-keys +// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#list-gpg-keys-for-a-user func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opts *ListOptions) ([]*GPGKey, *Response, error) { var u string if user != "" { diff --git a/github/users_keys.go b/github/users_keys.go index d823125c289..f12c01b9b07 100644 --- a/github/users_keys.go +++ b/github/users_keys.go @@ -27,7 +27,7 @@ func (k Key) String() string { // ListKeys lists the verified public keys for a user. Passing the empty // string will fetch keys for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/keys/#list-your-public-keys +// GitHub API docs: https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user func (s *UsersService) ListKeys(ctx context.Context, user string, opts *ListOptions) ([]*Key, *Response, error) { var u string if user != "" { diff --git a/github/users_projects_test.go b/github/users_projects_test.go index b186fbf07f7..7e3e5cbef8b 100644 --- a/github/users_projects_test.go +++ b/github/users_projects_test.go @@ -43,7 +43,7 @@ func TestUsersService_CreateProject(t *testing.T) { input := &CreateUserProjectOptions{Name: "Project Name", Body: String("Project body.")} - mux.HandleFunc("/users/projects", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/user/projects", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeProjectsPreview) From d75d6d71a04496d2463c14d58dd5b62bfbf629df Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Sun, 29 Mar 2020 23:07:29 -0400 Subject: [PATCH 05/12] Fix multiple urls --- github/activity_star.go | 1 + github/activity_watching.go | 1 + github/apps.go | 1 + github/apps_marketplace.go | 1 + github/gen-doc-urls.go | 5 +++-- github/gists.go | 1 + github/issues.go | 1 + github/issues_comments.go | 1 + github/orgs.go | 1 + github/orgs_members.go | 3 ++- github/pulls_comments.go | 1 + github/repos.go | 2 ++ github/users_followers.go | 3 +++ github/users_gpg_keys.go | 1 + github/users_keys.go | 1 + 15 files changed, 21 insertions(+), 3 deletions(-) diff --git a/github/activity_star.go b/github/activity_star.go index 921c6578304..158f395210a 100644 --- a/github/activity_star.go +++ b/github/activity_star.go @@ -68,6 +68,7 @@ type ActivityListStarredOptions struct { // will list the starred repositories for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/activity/starring/#list-repositories-starred-by-a-user +// 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 if user != "" { diff --git a/github/activity_watching.go b/github/activity_watching.go index cca07352db8..0265a08d0d9 100644 --- a/github/activity_watching.go +++ b/github/activity_watching.go @@ -53,6 +53,7 @@ func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, // the empty string will fetch watched repos for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-watched-by-a-user +// 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 if user != "" { diff --git a/github/apps.go b/github/apps.go index ee57b9eeb30..c0e8c9a0bfe 100644 --- a/github/apps.go +++ b/github/apps.go @@ -124,6 +124,7 @@ func (i Installation) String() string { // (e.g., https://github.com/settings/apps/:app_slug). // // GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-github-app +// GitHub API docs: https://developer.github.com/v3/apps/#get-the-authenticated-github-app func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) { var u string if appSlug != "" { diff --git a/github/apps_marketplace.go b/github/apps_marketplace.go index e12617aafe5..9026633e7aa 100644 --- a/github/apps_marketplace.go +++ b/github/apps_marketplace.go @@ -151,6 +151,7 @@ func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, acc // ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user. // // GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-subscriptions-for-the-authenticated-user +// 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" if s.Stubbed { diff --git a/github/gen-doc-urls.go b/github/gen-doc-urls.go index 471e8ac8241..d7a14dbe1a2 100644 --- a/github/gen-doc-urls.go +++ b/github/gen-doc-urls.go @@ -227,7 +227,7 @@ func validateRewriteURLs(usedHelpers usedHelpersMap, endpointsByFilename endpoin if !foundMatch { // Edit last stdRefLine, then remove it. cmt := endpoint.stdRefLines[len(endpoint.stdRefLines)-1] pos := fileRewriter.Position(cmt.Pos()) - logf("At byte offset %v:\nFOUND %q\nWANT: %q", pos.Offset, cmt.Text, line) + logf("stdRefLines=%v: At byte offset %v:\nFOUND %q\nWANT: %q", len(endpoint.stdRefLines), pos.Offset, cmt.Text, line) fileEdits = append(fileEdits, &FileEdit{ pos: pos, fromText: cmt.Text, @@ -240,13 +240,14 @@ func validateRewriteURLs(usedHelpers usedHelpersMap, endpointsByFilename endpoin cmt := endpoint.stdRefLines[0] if cmt.Text != line { pos := fileRewriter.Position(cmt.Pos()) - logf("At byte offset %v:\nFOUND %q\nWANT: %q", pos.Offset, cmt.Text, line) + logf("stdRefLines=1: At byte offset %v:\nFOUND %q\nWANT: %q", pos.Offset, cmt.Text, line) fileEdits = append(fileEdits, &FileEdit{ pos: pos, fromText: cmt.Text, toText: line, }) } + endpoint.stdRefLines = nil case len(endpoint.endpointComments) > 0: lastCmt := endpoint.endpointComments[len(endpoint.endpointComments)-1] // logf("lastCmt.Text=%q (len=%v)", lastCmt.Text, len(lastCmt.Text)) diff --git a/github/gists.go b/github/gists.go index 244dfe09810..026b5d15ee1 100644 --- a/github/gists.go +++ b/github/gists.go @@ -97,6 +97,7 @@ type GistListOptions struct { // user. // // GitHub API docs: https://developer.github.com/v3/gists/#list-gists-for-a-user +// 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 if user != "" { diff --git a/github/issues.go b/github/issues.go index e5bfb02a504..ccce80abc79 100644 --- a/github/issues.go +++ b/github/issues.go @@ -130,6 +130,7 @@ type PullRequestLinks struct { // repositories. // // GitHub API docs: https://developer.github.com/v3/issues/#list-issues-assigned-to-the-authenticated-user +// 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 if all { diff --git a/github/issues_comments.go b/github/issues_comments.go index 56b24c19179..5e5a754744e 100644 --- a/github/issues_comments.go +++ b/github/issues_comments.go @@ -50,6 +50,7 @@ type IssueListCommentsOptions struct { // ListComments lists all comments on the specified issue. Specifying an issue // 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-in-a-repository // GitHub API docs: https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opts *IssueListCommentsOptions) ([]*IssueComment, *Response, error) { var u string diff --git a/github/orgs.go b/github/orgs.go index 63fa8538c74..564231bc418 100644 --- a/github/orgs.go +++ b/github/orgs.go @@ -145,6 +145,7 @@ func (s *OrganizationsService) ListAll(ctx context.Context, opts *OrganizationsL // 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, opts *ListOptions) ([]*Organization, *Response, error) { var u string if user != "" { diff --git a/github/orgs_members.go b/github/orgs_members.go index aa282a112ed..0dfa92070d5 100644 --- a/github/orgs_members.go +++ b/github/orgs_members.go @@ -72,6 +72,7 @@ type ListMembersOptions struct { // 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/#public-members-list func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opts *ListMembersOptions) ([]*User, *Response, error) { var u string if opts != nil && opts.PublicOnly { @@ -206,8 +207,8 @@ func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opts *Lis // Passing an empty string for user will get the membership for the // authenticated user. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#get-your-organization-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#get-organization-membership +// GitHub API docs: https://developer.github.com/v3/orgs/members/#get-your-organization-membership func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org string) (*Membership, *Response, error) { var u string if user != "" { diff --git a/github/pulls_comments.go b/github/pulls_comments.go index b5423cd3270..741454aeefb 100644 --- a/github/pulls_comments.go +++ b/github/pulls_comments.go @@ -66,6 +66,7 @@ type PullRequestListCommentsOptions struct { // pull request number of 0 will return all comments on all pull requests for // the repository. // +// GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-comments-in-a-repository // GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request func (s *PullRequestsService) ListComments(ctx context.Context, owner string, repo string, number int, opts *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) { var u string diff --git a/github/repos.go b/github/repos.go index acaf92b0ec9..cfa69148d66 100644 --- a/github/repos.go +++ b/github/repos.go @@ -183,6 +183,7 @@ type RepositoryListOptions struct { // repositories for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/repos/#list-repositories-for-a-user +// 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 if user != "" { @@ -326,6 +327,7 @@ type createRepoRequest struct { // Note that only a subset of the repo fields are used and repo must // not be nil. // +// 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) { var u string diff --git a/github/users_followers.go b/github/users_followers.go index a429a1b2a3d..fa841c6c5de 100644 --- a/github/users_followers.go +++ b/github/users_followers.go @@ -13,6 +13,7 @@ import ( // ListFollowers lists the followers for a user. Passing the empty string will // fetch followers for the authenticated user. // +// GitHub API docs: https://developer.github.com/v3/users/followers/#list-followers-of-a-user // GitHub API docs: https://developer.github.com/v3/users/followers/#list-followers-of-the-authenticated-user func (s *UsersService) ListFollowers(ctx context.Context, user string, opts *ListOptions) ([]*User, *Response, error) { var u string @@ -43,6 +44,7 @@ func (s *UsersService) ListFollowers(ctx context.Context, user string, opts *Lis // ListFollowing lists the people that a user is following. Passing the empty // string will list people the authenticated user is following. // +// GitHub API docs: https://developer.github.com/v3/users/followers/#list-users-followed-by-another-user // GitHub API docs: https://developer.github.com/v3/users/followers/#list-users-followed-by-the-authenticated-user func (s *UsersService) ListFollowing(ctx context.Context, user string, opts *ListOptions) ([]*User, *Response, error) { var u string @@ -74,6 +76,7 @@ func (s *UsersService) ListFollowing(ctx context.Context, user string, opts *Lis // string for "user" will check if the authenticated user is following "target". // // GitHub API docs: https://developer.github.com/v3/users/followers/#check-if-one-user-follows-another +// GitHub API docs: https://developer.github.com/v3/users/followers/#check-if-you-are-following-a-user func (s *UsersService) IsFollowing(ctx context.Context, user, target string) (bool, *Response, error) { var u string if user != "" { diff --git a/github/users_gpg_keys.go b/github/users_gpg_keys.go index 1d4dab045af..20b6edfd5b2 100644 --- a/github/users_gpg_keys.go +++ b/github/users_gpg_keys.go @@ -45,6 +45,7 @@ type GPGEmail struct { // via Basic Auth or via OAuth with at least read:gpg_key scope. // // GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#list-gpg-keys-for-a-user +// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#list-your-gpg-keys func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opts *ListOptions) ([]*GPGKey, *Response, error) { var u string if user != "" { diff --git a/github/users_keys.go b/github/users_keys.go index f12c01b9b07..1091606a9f2 100644 --- a/github/users_keys.go +++ b/github/users_keys.go @@ -28,6 +28,7 @@ func (k Key) String() string { // string will fetch keys for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user +// GitHub API docs: https://developer.github.com/v3/users/keys/#list-your-public-keys func (s *UsersService) ListKeys(ctx context.Context, user string, opts *ListOptions) ([]*Key, *Response, error) { var u string if user != "" { From 7d3e90c9274b1f6a9fcf0e23800ac27336cc2616 Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Sun, 29 Mar 2020 23:08:38 -0400 Subject: [PATCH 06/12] Fix url --- github/apps_manifest.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/apps_manifest.go b/github/apps_manifest.go index 8d6ab3c8c45..9db76a30457 100644 --- a/github/apps_manifest.go +++ b/github/apps_manifest.go @@ -34,7 +34,7 @@ type AppConfig struct { // CompleteAppManifest completes the App manifest handshake flow for the given // code. // -// GitHub API docs: https://developer.github.com/apps/building-github-apps/creating-github-apps-from-a-manifest/#3-you-exchange-the-temporary-code-to-retrieve-the-app-configuration +// 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) From 005bc47a3a35157f44dcbc3c35bba5614076e82e Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Sun, 29 Mar 2020 23:15:13 -0400 Subject: [PATCH 07/12] Fix new file headers --- github/gen-doc-urls-activity-events_test.go | 5 +++++ github/gen-doc-urls-reactions_test.go | 5 +++++ github/gen-doc-urls.go | 3 --- github/gen-doc-urls_test.go | 5 +++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/github/gen-doc-urls-activity-events_test.go b/github/gen-doc-urls-activity-events_test.go index b3f30af259e..205ca029f3f 100644 --- a/github/gen-doc-urls-activity-events_test.go +++ b/github/gen-doc-urls-activity-events_test.go @@ -1,4 +1,9 @@ // -*- compile-command: "go test -v gen-doc-urls*.go"; -*- +// 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. + // +build ignore package main diff --git a/github/gen-doc-urls-reactions_test.go b/github/gen-doc-urls-reactions_test.go index 6dd0fa48ea7..49c72ca5860 100644 --- a/github/gen-doc-urls-reactions_test.go +++ b/github/gen-doc-urls-reactions_test.go @@ -1,4 +1,9 @@ // -*- compile-command: "go test -v gen-doc-urls*.go"; -*- +// 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. + // +build ignore package main diff --git a/github/gen-doc-urls.go b/github/gen-doc-urls.go index d7a14dbe1a2..3ad6c7fe03c 100644 --- a/github/gen-doc-urls.go +++ b/github/gen-doc-urls.go @@ -1,6 +1,3 @@ -// -*- compile-command: "go run gen-doc-urls.go -v"; -*- -// DO NOT COMMIT WITH COMPILE-COMMAND. - // Copyright 2020 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style diff --git a/github/gen-doc-urls_test.go b/github/gen-doc-urls_test.go index d6939f12a89..00a3c5a277c 100644 --- a/github/gen-doc-urls_test.go +++ b/github/gen-doc-urls_test.go @@ -1,4 +1,9 @@ // -*- compile-command: "go test -v gen-doc-urls*.go"; -*- +// 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. + // +build ignore package main From 47704dde40e788ccbe4e682d528aa5076a2eefab Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Sun, 29 Mar 2020 23:26:09 -0400 Subject: [PATCH 08/12] Update generator unit tests --- github/gen-doc-urls-activity-events_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/github/gen-doc-urls-activity-events_test.go b/github/gen-doc-urls-activity-events_test.go index 205ca029f3f..35a99ae9e65 100644 --- a/github/gen-doc-urls-activity-events_test.go +++ b/github/gen-doc-urls-activity-events_test.go @@ -1160,7 +1160,8 @@ func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org str // ListEventsPerformedByUser lists the events performed by a user. If publicOnly is // 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 +// 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 if publicOnly { @@ -1190,7 +1191,8 @@ func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user st // ListEventsReceivedByUser lists the events received by a user. If publicOnly is // 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 +// 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 if publicOnly { From fafab04d2d23d54bcbaee18c77a58e9147a9dc05 Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Wed, 8 Apr 2020 18:52:21 -0400 Subject: [PATCH 09/12] Move to update-urls --- github/github.go | 1 - go.mod | 1 - go.sum | 2 -- .../activity-events_test.go | 5 ++-- update-urls/go.mod | 5 ++++ update-urls/go.sum | 2 ++ github/gen-doc-urls.go => update-urls/main.go | 24 ++++++++++++++----- .../main_test.go | 5 ++-- .../reactions_test.go | 5 ++-- 9 files changed, 31 insertions(+), 19 deletions(-) rename github/gen-doc-urls-activity-events_test.go => update-urls/activity-events_test.go (99%) create mode 100644 update-urls/go.mod create mode 100644 update-urls/go.sum rename github/gen-doc-urls.go => update-urls/main.go (98%) rename github/gen-doc-urls_test.go => update-urls/main_test.go (99%) rename github/gen-doc-urls-reactions_test.go => update-urls/reactions_test.go (99%) diff --git a/github/github.go b/github/github.go index d71ca337f33..94f31a4c261 100644 --- a/github/github.go +++ b/github/github.go @@ -5,7 +5,6 @@ //go:generate go run gen-accessors.go //go:generate go run gen-stringify-test.go -//go:generate go run gen-doc-urls.go package github diff --git a/go.mod b/go.mod index 880f5ca96a3..6cf63d146dc 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/google/go-github/v30 require ( github.com/golang/protobuf v1.3.2 // indirect github.com/google/go-querystring v1.0.0 - github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/net v0.0.0-20190311183353-d8887717615a // indirect golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be diff --git a/go.sum b/go.sum index 02d8bb7c9de..dbab13e8b82 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,6 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= diff --git a/github/gen-doc-urls-activity-events_test.go b/update-urls/activity-events_test.go similarity index 99% rename from github/gen-doc-urls-activity-events_test.go rename to update-urls/activity-events_test.go index 35a99ae9e65..57dc8d1e35c 100644 --- a/github/gen-doc-urls-activity-events_test.go +++ b/update-urls/activity-events_test.go @@ -1,11 +1,10 @@ -// -*- compile-command: "go test -v gen-doc-urls*.go"; -*- +// -*- compile-command: "go test -v ."; -*- + // 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. -// +build ignore - package main import ( diff --git a/update-urls/go.mod b/update-urls/go.mod new file mode 100644 index 00000000000..3e168745cfc --- /dev/null +++ b/update-urls/go.mod @@ -0,0 +1,5 @@ +module github.com/google/go-github/update-urls + +go 1.14 + +require github.com/pmezard/go-difflib v1.0.0 diff --git a/update-urls/go.sum b/update-urls/go.sum new file mode 100644 index 00000000000..5d60ca74bbf --- /dev/null +++ b/update-urls/go.sum @@ -0,0 +1,2 @@ +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= diff --git a/github/gen-doc-urls.go b/update-urls/main.go similarity index 98% rename from github/gen-doc-urls.go rename to update-urls/main.go index 3ad6c7fe03c..73c2e9ca3aa 100644 --- a/github/gen-doc-urls.go +++ b/update-urls/main.go @@ -3,13 +3,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ignore - -// gen-doc-urls generates GitHub URL docs for each service endpoint. +// update-urls updates GitHub URL docs for each service endpoint. +// +// It is meant to be used periodically by go-github repo maintainers +// to update stale GitHub Developer v3 API documenation URLs. // -// It is meant to be used by go-github contributors in conjunction with the -// go generate tool before sending a PR to GitHub. -// Please see the CONTRIBUTING.md file for more information. +// Usage (from go-github directory): +// go run ./update-urls/main.go +// go generate ./... +// go test ./... +// go vet ./... package main import ( @@ -51,6 +54,8 @@ var ( "AdminService.CreateUserImpersonation": true, "AdminService.DeleteUserImpersonation": true, "AdminService.GetAdminStats": true, + "AdminService.RenameOrg": true, + "AdminService.RenameOrgByName": true, "AdminService.UpdateTeamLDAPMapping": true, "AdminService.UpdateUserLDAPMapping": true, "AppsService.FindRepositoryInstallationByID": true, @@ -110,6 +115,10 @@ func main() { return !strings.HasSuffix(fi.Name(), "_test.go") && !strings.HasPrefix(fi.Name(), skipPrefix) } + if err := os.Chdir("./github"); err != nil { + log.Fatalf("Please run this from the go-github directory.") + } + pkgs, err := parser.ParseDir(fset, ".", sourceFilter, parser.ParseComments) if err != nil { log.Fatal(err) @@ -413,6 +422,9 @@ func (rafi *realAstFileIterator) Reset() { rafi.closed = true close(rafi.ch) logf("Closed channel after sending %v files", count) + if count == 0 { + log.Fatalf("Processed no files. Did you run this from the go-github directory?") + } }() } diff --git a/github/gen-doc-urls_test.go b/update-urls/main_test.go similarity index 99% rename from github/gen-doc-urls_test.go rename to update-urls/main_test.go index 00a3c5a277c..531e1c1f019 100644 --- a/github/gen-doc-urls_test.go +++ b/update-urls/main_test.go @@ -1,11 +1,10 @@ -// -*- compile-command: "go test -v gen-doc-urls*.go"; -*- +// -*- compile-command: "go test -v ."; -*- + // 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. -// +build ignore - package main import ( diff --git a/github/gen-doc-urls-reactions_test.go b/update-urls/reactions_test.go similarity index 99% rename from github/gen-doc-urls-reactions_test.go rename to update-urls/reactions_test.go index 49c72ca5860..27a1d7f9887 100644 --- a/github/gen-doc-urls-reactions_test.go +++ b/update-urls/reactions_test.go @@ -1,11 +1,10 @@ -// -*- compile-command: "go test -v gen-doc-urls*.go"; -*- +// -*- compile-command: "go test -v ."; -*- + // 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. -// +build ignore - package main import ( From 60798b71e0a45c97724dec699c5d2c5d55b5b98e Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Wed, 8 Apr 2020 18:56:30 -0400 Subject: [PATCH 10/12] Remove emacs compile-command --- update-urls/activity-events_test.go | 2 -- update-urls/main_test.go | 2 -- update-urls/reactions_test.go | 2 -- 3 files changed, 6 deletions(-) diff --git a/update-urls/activity-events_test.go b/update-urls/activity-events_test.go index 57dc8d1e35c..6f4dbeb4b13 100644 --- a/update-urls/activity-events_test.go +++ b/update-urls/activity-events_test.go @@ -1,5 +1,3 @@ -// -*- compile-command: "go test -v ."; -*- - // Copyright 2020 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style diff --git a/update-urls/main_test.go b/update-urls/main_test.go index 531e1c1f019..e77411a022c 100644 --- a/update-urls/main_test.go +++ b/update-urls/main_test.go @@ -1,5 +1,3 @@ -// -*- compile-command: "go test -v ."; -*- - // Copyright 2020 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style diff --git a/update-urls/reactions_test.go b/update-urls/reactions_test.go index 27a1d7f9887..1ef696f7799 100644 --- a/update-urls/reactions_test.go +++ b/update-urls/reactions_test.go @@ -1,5 +1,3 @@ -// -*- compile-command: "go test -v ."; -*- - // Copyright 2020 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style From 18378b31fc263503ae9b1ac80ae611f60de7e9c9 Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Thu, 9 Apr 2020 17:17:12 -0400 Subject: [PATCH 11/12] Update teams --- github/teams.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/github/teams.go b/github/teams.go index b9ff4d8c086..6eab37fd545 100644 --- a/github/teams.go +++ b/github/teams.go @@ -768,7 +768,7 @@ func (s *TeamsService) ListIDPGroupsInOrganization(ctx context.Context, org stri // 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-legacy +// 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) @@ -808,7 +808,7 @@ func (s *TeamsService) ListIDPGroupsForTeamBySlug(ctx context.Context, org, slug // 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-legacy +// 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) From f13116d057ac071b28f499da42988b95df8a672e Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Thu, 9 Apr 2020 18:45:04 -0400 Subject: [PATCH 12/12] Fix receivers and other breaking changes --- github/gitignore.go | 4 ++-- github/reactions.go | 10 +++++----- github/repos_keys.go | 20 ------------------- github/repos_keys_test.go | 37 ----------------------------------- github/users_projects.go | 2 +- github/users_projects_test.go | 2 +- 6 files changed, 9 insertions(+), 66 deletions(-) diff --git a/github/gitignore.go b/github/gitignore.go index 2f691bc323e..dc2eab757ae 100644 --- a/github/gitignore.go +++ b/github/gitignore.go @@ -29,7 +29,7 @@ func (g Gitignore) String() string { // List all available Gitignore 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) if err != nil { return nil, nil, err @@ -47,7 +47,7 @@ func (s GitignoresService) List(ctx context.Context) ([]string, *Response, error // Get a Gitignore by name. // // GitHub API docs: https://developer.github.com/v3/gitignore/#get-a-single-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) req, err := s.client.NewRequest("GET", u, nil) if err != nil { diff --git a/github/reactions.go b/github/reactions.go index 1602032e221..7dd8b7c9db3 100644 --- a/github/reactions.go +++ b/github/reactions.go @@ -89,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". // // 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) body := &Reaction{Content: String(content)} @@ -161,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". // // 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) body := &Reaction{Content: String(content)} @@ -233,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". // // 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) body := &Reaction{Content: String(content)} @@ -305,7 +305,7 @@ func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, // 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 -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) body := &Reaction{Content: String(content)} @@ -479,7 +479,7 @@ func (s *ReactionsService) DeleteTeamDiscussionCommentReactionByOrgIDAndTeamID(c return s.deleteReaction(ctx, url) } -func (s ReactionsService) deleteReaction(ctx context.Context, url string) (*Response, error) { +func (s *ReactionsService) deleteReaction(ctx context.Context, url string) (*Response, error) { req, err := s.client.NewRequest(http.MethodDelete, url, nil) if err != nil { return nil, err diff --git a/github/repos_keys.go b/github/repos_keys.go index 64ee7422a07..11b3b6f6840 100644 --- a/github/repos_keys.go +++ b/github/repos_keys.go @@ -76,26 +76,6 @@ func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo 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. // // GitHub API docs: https://developer.github.com/v3/repos/keys/#delete diff --git a/github/repos_keys_test.go b/github/repos_keys_test.go index 75a17356edd..7a9a4b09f7b 100644 --- a/github/repos_keys_test.go +++ b/github/repos_keys_test.go @@ -109,43 +109,6 @@ func TestRepositoriesService_CreateKey_invalidOwner(t *testing.T) { testURLParseError(t, err) } -func TestRepositoriesService_EditKey(t *testing.T) { - client, mux, _, teardown := setup() - defer teardown() - - input := &Key{Key: String("k"), Title: String("t")} - - mux.HandleFunc("/repos/o/r/keys/1", func(w http.ResponseWriter, r *http.Request) { - v := new(Key) - json.NewDecoder(r.Body).Decode(v) - - testMethod(t, r, "PATCH") - if !reflect.DeepEqual(v, input) { - t.Errorf("Request body = %+v, want %+v", v, input) - } - - fmt.Fprint(w, `{"id":1}`) - }) - - key, _, err := client.Repositories.EditKey(context.Background(), "o", "r", 1, input) - if err != nil { - t.Errorf("Repositories.EditKey returned error: %v", err) - } - - want := &Key{ID: Int64(1)} - if !reflect.DeepEqual(key, want) { - t.Errorf("Repositories.EditKey returned %+v, want %+v", key, want) - } -} - -func TestRepositoriesService_EditKey_invalidOwner(t *testing.T) { - client, _, _, teardown := setup() - defer teardown() - - _, _, err := client.Repositories.EditKey(context.Background(), "%", "%", 1, nil) - testURLParseError(t, err) -} - func TestRepositoriesService_DeleteKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() diff --git a/github/users_projects.go b/github/users_projects.go index 64e85a03226..1357055040c 100644 --- a/github/users_projects.go +++ b/github/users_projects.go @@ -49,7 +49,7 @@ type CreateUserProjectOptions struct { // // GitHub API docs: https://developer.github.com/v3/projects/#create-a-user-project func (s *UsersService) CreateProject(ctx context.Context, opts *CreateUserProjectOptions) (*Project, *Response, error) { - u := "users/projects" + u := "user/projects" req, err := s.client.NewRequest("POST", u, opts) if err != nil { return nil, nil, err diff --git a/github/users_projects_test.go b/github/users_projects_test.go index b186fbf07f7..7e3e5cbef8b 100644 --- a/github/users_projects_test.go +++ b/github/users_projects_test.go @@ -43,7 +43,7 @@ func TestUsersService_CreateProject(t *testing.T) { input := &CreateUserProjectOptions{Name: "Project Name", Body: String("Project body.")} - mux.HandleFunc("/users/projects", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/user/projects", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeProjectsPreview)