pax_global_header00006660000000000000000000000064135350127050014513gustar00rootroot0000000000000052 comment=9686ff0746200cf521ce225525b421e13b4eac1a go-github-28.1.1/000077500000000000000000000000001353501270500134715ustar00rootroot00000000000000go-github-28.1.1/.codecov.yml000066400000000000000000000001101353501270500157040ustar00rootroot00000000000000ignore: # ignore auto-generated code - "github/github-accessors.go" go-github-28.1.1/.gitignore000066400000000000000000000000241353501270500154550ustar00rootroot00000000000000*.test coverage.out go-github-28.1.1/.travis.yml000066400000000000000000000014101353501270500155760ustar00rootroot00000000000000language: go go: - "1.x" - "1.12.x" - master matrix: allow_failures: - go: master fast_finish: true cache: directories: - $HOME/.cache/go-build - $HOME/gopath/pkg/mod env: global: - GO111MODULE=on script: - diff -u <(echo -n) <(gofmt -d -s .) - go generate -x ./... && git diff --exit-code; code=$?; git checkout -- .; (exit $code) # Check that go generate ./... produces a zero diff; clean up any changes afterwards. - go vet ./... - go test -v -race -coverprofile=coverage.txt -covermode=atomic ./... - go test -v -tags=integration -run=^$ ./test/integration # Check that integration test builds successfully, but don't run any of the tests (they hit live GitHub API). after_success: - bash <(curl -s https://codecov.io/bash) go-github-28.1.1/AUTHORS000066400000000000000000000225331353501270500145460ustar00rootroot00000000000000# This is the official list of go-github authors for copyright purposes. # # This does not necessarily list everyone who has contributed code, since in # some cases, their employer may be the copyright holder. To see the full list # of contributors, see the revision history in source control or # https://github.com/google/go-github/graphs/contributors. # # Authors who wish to be recognized in this file should add themselves (or # their employer, as appropriate). 178inaba Abhinav Gupta adrienzieba Ahmed Hagy Aidan Steele Ainsley Chong Akeda Bagus Akhil Mohan Alec Thomas Aleks Clark Alex Bramley Alexander Harkness Allen Sun Amey Sakhadeo Andreas Garnæs Andrew Ryabchun Andy Grunwald Andy Hume Andy Lindeman anjanashenoy Anshuman Bhartiya Antoine Antoine Pelisse Anubha Kushwaha appilon Aravind Arda Kuyumcu Arıl Bozoluk Austin Dizzy Ben Batha Benjamen Keroack Beshr Kayali Beyang Liu Billy Lynch Björn Häuser Brad Harris Brad Moylan Bradley Falzon Brandon Cook Brian Egizi Bryan Boreham Cami Diez Carlos Alexandro Becker Carlos Tadeu Panato Junior chandresh-pancholi Charles Fenwick Elliott Charlie Yan Chris King Chris Roche Chris Schaefer chrisforrette Christian Muehlhaeuser Christoph Sassenberg Colin Misare Craig Peterson Cristian Maglie Daehyeok Mun Daniel Leavitt Daniel Nilsson Dave Du Cros Dave Henderson David Deng David Jannotta David Ji Davide Zipeto Dennis Webb Dhi Aurrahman Diego Lapiduz Dmitri Shuralyov dmnlk Don Petersen Doug Turner Drew Fradette Eli Uriegas Elliott Beach Emerson Wood eperm Erick Fejta erwinvaneyk Evan Elias Fabrice Felix Geisendörfer Filippo Valsorda Florian Forster Francesc Gil Francis Fredrik Jönsson Garrett Squire George Kontridze Georgy Buranov Gnahz Google Inc. Grachev Mikhail griffin_stewie Guillaume Jacquet Guz Alexander Guðmundur Bjarni Ólafsson Hanno Hecker Hari haran haya14busa Huy Tr huydx i2bskn Isao Jonas isqua Jameel Haffejee Jan Kosecki Javier Campanini Jens Rantil Jeremy Morris Jesse Newland Jihoon Chung Jimmi Dyson Joan Saum Joe Tsai John Barton John Engelman Jordan Brockopp Jordan Sussman Joshua Bezaleel Abednego JP Phillips jpbelanger-mtl Juan Basso Julien Garcia Gonzalez Julien Rostand Junya Kono Justin Abrahms Jusung Lee jzhoucliqr Katrina Owen Kautilya Tripathi < tripathi.kautilya@gmail.com> Kautilya Tripathi Keita Urashima Kevin Burke Konrad Malawski Kookheon Kwon Krzysztof Kowalczyk Kshitij Saraogi kyokomi Laurent Verdoïa Liam Galvin Lovro Mažgon Lucas Alcantara Luke Evers Luke Kysow Luke Roberts Luke Young Maksim Zhylinski Mark Tareshawty Martin-Louis Bright Marwan Sulaiman Masayuki Izumi Mat Geist Matt Matt Brender Matt Gaunt Matt Landis Maxime Bury Michael Spiegel Michael Tiller Michał Glapa Nadav Kaner Nathan VanBenschoten Navaneeth Suresh Neil O'Toole Nick Miyake Nick Spragg Nikhita Raghunath Noah Zoschke ns-cweber Oleg Kovalov Ondřej Kupka Palash Nigam Panagiotis Moustafellos Parham Alvani Parker Moore parkhyukjun89 Pavel Shtanko Pete Wagner Petr Shevtsov Pierre Carrier Piotr Zurek Quentin Leffray Quinn Slack Rackspace US, Inc. Radek Simko Radliński Ignacy Rajendra arora Ranbir Singh RaviTeja Pothana rc1140 Red Hat, Inc. Ricco Førgaard Rob Figueiredo Rohit Upadhyay Ronak Jain Ruben Vereecken Ryan Leung Ryan Lower Sahil Dua saisi Sam Minnée Sandeep Sukhani Sander van Harmelen Sanket Payghan Sarasa Kisaragi Sean Wang Sebastian Mandrean Sebastian Mæland Pedersen Sergey Romanov Sevki Shagun Khemka shakeelrao Shawn Catanzarite Shawn Smith Shrikrishna Singh sona-tar SoundCloud, Ltd. Sridhar Mocherla SriVignessh Pss Stian Eikeland Szymon Kodrebski Tasya Aditya Rukmana Thomas Bruyelle Timothée Peignier Trey Tacon ttacon Vaibhav Singh Varadarajan Aravamudhan Victor Castell Victor Vrantchan Vlad Ungureanu Wasim Thabraze Will Maier William Bailey William Cooke xibz Yann Malet Yannick Utard Yicheng Qin Yosuke Akatsuka Yumikiyo Osanai Zach Latta go-github-28.1.1/CONTRIBUTING.md000066400000000000000000000142021353501270500157210ustar00rootroot00000000000000# How to contribute # We'd love to accept your patches and contributions to this project. There are a just a few small guidelines you need to follow. ## Contributor License Agreement ## Contributions to any Google project must be accompanied by a Contributor License Agreement. This is not a copyright **assignment**, it simply gives Google permission to use and redistribute your contributions as part of the project. Head over to to see your current agreements on file or to sign a new one. You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again. ## Reporting issues ## Bugs, feature requests, and development-related questions should be directed to our [GitHub issue tracker](https://github.com/google/go-github/issues). If reporting a bug, please try and provide as much context as possible such as your operating system, Go version, and anything else that might be relevant to the bug. For feature requests, please explain what you're trying to do, and how the requested feature would help you do that. Security related bugs can either be reported in the issue tracker, or if they are more sensitive, emailed to . ## Submitting a patch ## 1. It's generally best to start by opening a new issue describing the bug or feature you're intending to fix. Even if you think it's relatively minor, it's helpful to know what people are working on. Mention in the initial issue that you are planning to work on that bug or feature so that it can be assigned to you. 1. Follow the normal process of [forking][] the project, and setup a new branch to work in. It's important that each group of changes be done in separate branches in order to ensure that a pull request only includes the commits related to that bug or feature. 1. Go makes it very simple to ensure properly formatted code, so always run `go fmt` on your code before committing it. You should also run [golint][] over your code. As noted in the [golint readme][], it's not strictly necessary that your code be completely "lint-free", but this will help you find common style issues. 1. Any significant changes should almost always be accompanied by tests. The project already has good test coverage, so look at some of the existing tests if you're unsure how to go about it. [gocov][] and [gocov-html][] are invaluable tools for seeing which parts of your code aren't being exercised by your tests. 1. Please run: * `go generate github.com/google/go-github/...` * `go test github.com/google/go-github/...` * `go vet github.com/google/go-github/...` 1. Do your best to have [well-formed commit messages][] for each change. This provides consistency throughout the project, and ensures that commit messages are able to be formatted properly by various git tools. 1. Finally, push the commits to your fork and submit a [pull request][]. [forking]: https://help.github.com/articles/fork-a-repo [golint]: https://github.com/golang/lint [golint readme]: https://github.com/golang/lint/blob/master/README.md [gocov]: https://github.com/axw/gocov [gocov-html]: https://github.com/matm/gocov-html [well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html [squash]: http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits [pull request]: https://help.github.com/articles/creating-a-pull-request ## Other notes on code organization ## Currently, everything is defined in the main `github` package, with API methods broken into separate service objects. These services map directly to how the [GitHub API documentation][] is organized, so use that as your guide for where to put new methods. Code is organized in files also based pretty closely on the GitHub API documentation, following the format `{service}_{api}.go`. For example, methods defined at live in [repos_hooks.go][]. [GitHub API documentation]: https://developer.github.com/v3/ [repos_hooks.go]: https://github.com/google/go-github/blob/master/github/repos_hooks.go ## Maintainer's Guide ## (These notes are mostly only for people merging in pull requests.) **Verify CLAs.** CLAs must be on file for the pull request submitter and commit author(s). Google's CLA verification system should handle this automatically and will set commit statuses as appropriate. If there's ever any question about a pull request, ask [willnorris](https://github.com/willnorris). **Always try to maintain a clean, linear git history.** With very few exceptions, running `git log` should not show a bunch of branching and merging. Never use the GitHub "merge" button, since it always creates a merge commit. Instead, check out the pull request locally ([these git aliases help][git-aliases]), then cherry-pick or rebase them onto master. If there are small cleanup commits, especially as a result of addressing code review comments, these should almost always be squashed down to a single commit. Don't bother squashing commits that really deserve to be separate though. If needed, feel free to amend additional small changes to the code or commit message that aren't worth going through code review for. If you made any changes like squashing commits, rebasing onto master, etc, then GitHub won't recognize that this is the same commit in order to mark the pull request as "merged". So instead, amend the commit message to include a line "Fixes #0", referencing the pull request number. This would be in addition to any other "Fixes" lines for closing related issues. If you forget to do this, you can also leave a comment on the pull request [like this][rebase-comment]. If you made any other changes, it's worth noting that as well, [like this][modified-comment]. [git-aliases]: https://github.com/willnorris/dotfiles/blob/d640d010c23b1116bdb3d4dc12088ed26120d87d/git/.gitconfig#L13-L15 [rebase-comment]: https://github.com/google/go-github/pull/277#issuecomment-183035491 [modified-comment]: https://github.com/google/go-github/pull/280#issuecomment-184859046 go-github-28.1.1/LICENSE000066400000000000000000000027161353501270500145040ustar00rootroot00000000000000Copyright (c) 2013 The go-github AUTHORS. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. go-github-28.1.1/README.md000066400000000000000000000244531353501270500147600ustar00rootroot00000000000000# go-github # [![GoDoc](https://godoc.org/github.com/google/go-github/github?status.svg)](https://godoc.org/github.com/google/go-github/github) [![Build Status](https://travis-ci.org/google/go-github.svg?branch=master)](https://travis-ci.org/google/go-github) [![Test Coverage](https://codecov.io/gh/google/go-github/branch/master/graph/badge.svg)](https://codecov.io/gh/google/go-github) [![Discuss at go-github@googlegroups.com](https://img.shields.io/badge/discuss-go--github%40googlegroups.com-blue.svg)](https://groups.google.com/group/go-github) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/796/badge)](https://bestpractices.coreinfrastructure.org/projects/796) go-github is a Go client library for accessing the [GitHub API v3][]. Currently, **go-github requires Go version 1.9 or greater**. go-github tracks [Go's version support policy][support-policy]. We do our best not to break older versions of Go if we don't have to, but due to tooling constraints, we don't always test older versions. [support-policy]: https://golang.org/doc/devel/release.html#policy If you're interested in using the [GraphQL API v4][], the recommended library is [shurcooL/githubv4][]. ## Usage ## ```go import "github.com/google/go-github/v28/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) import "github.com/google/go-github/github" // with go modules disabled ``` Construct a new GitHub client, then use the various services on the client to access different parts of the GitHub API. For example: ```go client := github.NewClient(nil) // list all organizations for user "willnorris" orgs, _, err := client.Organizations.List(context.Background(), "willnorris", nil) ``` Some API methods have optional parameters that can be passed. For example: ```go client := github.NewClient(nil) // list public repositories for org "github" opt := &github.RepositoryListByOrgOptions{Type: "public"} repos, _, err := client.Repositories.ListByOrg(context.Background(), "github", opt) ``` The services of a client divide the API into logical chunks and correspond to the structure of the GitHub API documentation at https://developer.github.com/v3/. NOTE: Using the [context](https://godoc.org/context) package, one can easily pass cancelation signals and deadlines to various services of the client for handling a request. In case there is no context available, then `context.Background()` can be used as a starting point. For more sample code snippets, head over to the [example](https://github.com/google/go-github/tree/master/example) directory. ### Authentication ### The go-github library does not directly handle authentication. Instead, when creating a new client, pass an `http.Client` that can handle authentication for you. The easiest and recommended way to do this is using the [oauth2][] library, but you can always use any other library that provides an `http.Client`. If you have an OAuth2 access token (for example, a [personal API token][]), you can use it with the oauth2 library using: ```go import "golang.org/x/oauth2" func main() { ctx := context.Background() ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: "... your access token ..."}, ) tc := oauth2.NewClient(ctx, ts) client := github.NewClient(tc) // list all repositories for the authenticated user repos, _, err := client.Repositories.List(ctx, "", nil) } ``` Note that when using an authenticated Client, all calls made by the client will include the specified OAuth token. Therefore, authenticated clients should almost never be shared between different users. See the [oauth2 docs][] for complete instructions on using that library. For API methods that require HTTP Basic Authentication, use the [`BasicAuthTransport`](https://godoc.org/github.com/google/go-github/github#BasicAuthTransport). GitHub Apps authentication can be provided by the [ghinstallation](https://github.com/bradleyfalzon/ghinstallation) package. ```go import "github.com/bradleyfalzon/ghinstallation" func main() { // Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99. itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "2016-10-19.private-key.pem") if err != nil { // Handle error. } // Use installation transport with client. client := github.NewClient(&http.Client{Transport: itr}) // Use client... } ``` ### Rate Limiting ### GitHub imposes a rate limit on all API clients. Unauthenticated clients are limited to 60 requests per hour, while authenticated clients can make up to 5,000 requests per hour. The Search API has a custom rate limit. Unauthenticated clients are limited to 10 requests per minute, while authenticated clients can make up to 30 requests per minute. To receive the higher rate limit when making calls that are not issued on behalf of a user, use `UnauthenticatedRateLimitedTransport`. The returned `Response.Rate` value contains the rate limit information from the most recent API call. If a recent enough response isn't available, you can use `RateLimits` to fetch the most up-to-date rate limit data for the client. To detect an API rate limit error, you can check if its type is `*github.RateLimitError`: ```go repos, _, err := client.Repositories.List(ctx, "", nil) if _, ok := err.(*github.RateLimitError); ok { log.Println("hit rate limit") } ``` Learn more about GitHub rate limiting at https://developer.github.com/v3/#rate-limiting. ### Accepted Status ### Some endpoints may return a 202 Accepted status code, meaning that the information required is not yet ready and was scheduled to be gathered on the GitHub side. Methods known to behave like this are documented specifying this behavior. To detect this condition of error, you can check if its type is `*github.AcceptedError`: ```go stats, _, err := client.Repositories.ListContributorsStats(ctx, org, repo) if _, ok := err.(*github.AcceptedError); ok { log.Println("scheduled on GitHub side") } ``` ### Conditional Requests ### The GitHub API has good support for conditional requests which will help prevent you from burning through your rate limit, as well as help speed up your application. `go-github` does not handle conditional requests directly, but is instead designed to work with a caching `http.Transport`. We recommend using https://github.com/gregjones/httpcache for that. Learn more about GitHub conditional requests at https://developer.github.com/v3/#conditional-requests. ### Creating and Updating Resources ### All structs for GitHub resources use pointer values for all non-repeated fields. This allows distinguishing between unset fields and those set to a zero-value. Helper functions have been provided to easily create these pointers for string, bool, and int values. For example: ```go // create a new private repository named "foo" repo := &github.Repository{ Name: github.String("foo"), Private: github.Bool(true), } client.Repositories.Create(ctx, "", repo) ``` Users who have worked with protocol buffers should find this pattern familiar. ### Pagination ### All requests for resource collections (repos, pull requests, issues, etc.) support pagination. Pagination options are described in the `github.ListOptions` struct and passed to the list methods directly or as an embedded type of a more specific list options struct (for example `github.PullRequestListOptions`). Pages information is available via the `github.Response` struct. ```go client := github.NewClient(nil) opt := &github.RepositoryListByOrgOptions{ ListOptions: github.ListOptions{PerPage: 10}, } // get all pages of results var allRepos []*github.Repository for { repos, resp, err := client.Repositories.ListByOrg(ctx, "github", opt) if err != nil { return err } allRepos = append(allRepos, repos...) if resp.NextPage == 0 { break } opt.Page = resp.NextPage } ``` For complete usage of go-github, see the full [package docs][]. [GitHub API v3]: https://developer.github.com/v3/ [oauth2]: https://github.com/golang/oauth2 [oauth2 docs]: https://godoc.org/golang.org/x/oauth2 [personal API token]: https://github.com/blog/1509-personal-api-tokens [package docs]: https://godoc.org/github.com/google/go-github/github [GraphQL API v4]: https://developer.github.com/v4/ [shurcooL/githubv4]: https://github.com/shurcooL/githubv4 ### Integration Tests ### You can run integration tests from the `test` directory. See the integration tests [README](test/README.md). ## Roadmap ## This library is being initially developed for an internal application at Google, so API methods will likely be implemented in the order that they are needed by that application. You can track the status of implementation in [this Google spreadsheet][roadmap]. [roadmap]: https://docs.google.com/spreadsheet/ccc?key=0ApoVX4GOiXr-dGNKN1pObFh6ek1DR2FKUjBNZ1FmaEE&usp=sharing ## Contributing ## I would like to cover the entire GitHub API and contributions are of course always welcome. The calling pattern is pretty well established, so adding new methods is relatively straightforward. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for details. ## Versioning ## In general, go-github follows [semver](https://semver.org/) as closely as we can for tagging releases of the package. For self-contained libraries, the application of semantic versioning is relatively straightforward and generally understood. But because go-github is a client library for the GitHub API, which itself changes behavior, and because we are typically pretty aggressive about implementing preview features of the GitHub API, we've adopted the following versioning policy: * We increment the **major version** with any incompatible change to non-preview functionality, including changes to the exported Go API surface or behavior of the API. * We increment the **minor version** with any backwards-compatible changes to functionality, as well as any changes to preview functionality in the GitHub API. GitHub makes no guarantee about the stability of preview functionality, so neither do we consider it a stable part of the go-github API. * We increment the **patch version** with any backwards-compatible bug fixes. Preview functionality may take the form of entire methods or simply additional data returned from an otherwise non-preview method. Refer to the GitHub API documentation for details on preview functionality. ## License ## This library is distributed under the BSD-style license found in the [LICENSE](./LICENSE) file. go-github-28.1.1/example/000077500000000000000000000000001353501270500151245ustar00rootroot00000000000000go-github-28.1.1/example/appengine/000077500000000000000000000000001353501270500170725ustar00rootroot00000000000000go-github-28.1.1/example/appengine/app.go000066400000000000000000000022161353501270500202020ustar00rootroot00000000000000// Copyright 2017 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 demo provides an app that shows how to use the github package on // Google App Engine. package demo import ( "fmt" "net/http" "os" "github.com/google/go-github/v28/github" "golang.org/x/oauth2" "google.golang.org/appengine" "google.golang.org/appengine/log" ) func init() { http.HandleFunc("/", handler) } func handler(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } ctx := appengine.NewContext(r) ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: os.Getenv("GITHUB_AUTH_TOKEN")}, ) tc := oauth2.NewClient(ctx, ts) client := github.NewClient(tc) commits, _, err := client.Repositories.ListCommits(ctx, "google", "go-github", nil) if err != nil { log.Errorf(ctx, "ListCommits: %v", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/plain; charset=utf-8") for _, commit := range commits { fmt.Fprintln(w, commit.GetHTMLURL()) } } go-github-28.1.1/example/appengine/app.yaml000066400000000000000000000004511353501270500205360ustar00rootroot00000000000000# Copyright 2017 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. runtime: go api_version: go1 handlers: - url: /.* script: _go_app env_variables: GITHUB_AUTH_TOKEN: "-your-auth-token-here-" go-github-28.1.1/example/basicauth/000077500000000000000000000000001353501270500170675ustar00rootroot00000000000000go-github-28.1.1/example/basicauth/main.go000066400000000000000000000025661353501270500203530ustar00rootroot00000000000000// Copyright 2015 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. // The basicauth command demonstrates using the github.BasicAuthTransport, // including handling two-factor authentication. This won't currently work for // accounts that use SMS to receive one-time passwords. package main import ( "bufio" "context" "fmt" "os" "strings" "syscall" "github.com/google/go-github/v28/github" "golang.org/x/crypto/ssh/terminal" ) func main() { r := bufio.NewReader(os.Stdin) fmt.Print("GitHub Username: ") username, _ := r.ReadString('\n') fmt.Print("GitHub Password: ") bytePassword, _ := terminal.ReadPassword(int(syscall.Stdin)) password := string(bytePassword) tp := github.BasicAuthTransport{ Username: strings.TrimSpace(username), Password: strings.TrimSpace(password), } client := github.NewClient(tp.Client()) ctx := context.Background() user, _, err := client.Users.Get(ctx, "") // Is this a two-factor auth error? If so, prompt for OTP and try again. if _, ok := err.(*github.TwoFactorAuthError); ok { fmt.Print("\nGitHub OTP: ") otp, _ := r.ReadString('\n') tp.OTP = strings.TrimSpace(otp) user, _, err = client.Users.Get(ctx, "") } if err != nil { fmt.Printf("\nerror: %v\n", err) return } fmt.Printf("\n%v\n", github.Stringify(user)) } go-github-28.1.1/example/commitpr/000077500000000000000000000000001353501270500167565ustar00rootroot00000000000000go-github-28.1.1/example/commitpr/main.go000066400000000000000000000202701353501270500202320ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // The commitpr command utilizes go-github as a CLI tool for // pushing files to a branch and creating a pull request from it. // It takes an auth token as an environment variable and creates // the commit and the PR under the account affiliated with that token. // // The purpose of this example is to show how to use refs, trees and commits to // create commits and pull requests. // // Note, if you want to push a single file, you probably prefer to use the // content API. An example is available here: // https://godoc.org/github.com/google/go-github/github#example-RepositoriesService-CreateFile // // Note, for this to work at least 1 commit is needed, so you if you use this // after creating a repository you might want to make sure you set `AutoInit` to // `true`. package main import ( "context" "errors" "flag" "fmt" "io/ioutil" "log" "os" "strings" "time" "github.com/google/go-github/v28/github" "golang.org/x/oauth2" ) var ( sourceOwner = flag.String("source-owner", "", "Name of the owner (user or org) of the repo to create the commit in.") sourceRepo = flag.String("source-repo", "", "Name of repo to create the commit in.") commitMessage = flag.String("commit-message", "", "Content of the commit message.") commitBranch = flag.String("commit-branch", "", "Name of branch to create the commit in. If it does not already exists, it will be created using the `base-branch` parameter") baseBranch = flag.String("base-branch", "master", "Name of branch to create the `commit-branch` from.") prRepoOwner = flag.String("merge-repo-owner", "", "Name of the owner (user or org) of the repo to create the PR against. If not specified, the value of the `-source-owner` flag will be used.") prRepo = flag.String("merge-repo", "", "Name of repo to create the PR against. If not specified, the value of the `-source-repo` flag will be used.") prBranch = flag.String("merge-branch", "master", "Name of branch to create the PR against (the one you want to merge your branch in via the PR).") prSubject = flag.String("pr-title", "", "Title of the pull request. If not specified, no pull request will be created.") prDescription = flag.String("pr-text", "", "Text to put in the description of the pull request.") sourceFiles = flag.String("files", "", `Comma-separated list of files to commit and their location. The local file is separated by its target location by a semi-colon. If the file should be in the same location with the same name, you can just put the file name and omit the repetition. Example: README.md,main.go:github/examples/commitpr/main.go`) authorName = flag.String("author-name", "", "Name of the author of the commit.") authorEmail = flag.String("author-email", "", "Email of the author of the commit.") ) var client *github.Client var ctx = context.Background() // getRef returns the commit branch reference object if it exists or creates it // from the base branch before returning it. func getRef() (ref *github.Reference, err error) { if ref, _, err = client.Git.GetRef(ctx, *sourceOwner, *sourceRepo, "refs/heads/"+*commitBranch); err == nil { return ref, nil } // We consider that an error means the branch has not been found and needs to // be created. if *commitBranch == *baseBranch { return nil, errors.New("The commit branch does not exist but `-base-branch` is the same as `-commit-branch`") } if *baseBranch == "" { return nil, errors.New("The `-base-branch` should not be set to an empty string when the branch specified by `-commit-branch` does not exists") } var baseRef *github.Reference if baseRef, _, err = client.Git.GetRef(ctx, *sourceOwner, *sourceRepo, "refs/heads/"+*baseBranch); err != nil { return nil, err } newRef := &github.Reference{Ref: github.String("refs/heads/" + *commitBranch), Object: &github.GitObject{SHA: baseRef.Object.SHA}} ref, _, err = client.Git.CreateRef(ctx, *sourceOwner, *sourceRepo, newRef) return ref, err } // getTree generates the tree to commit based on the given files and the commit // of the ref you got in getRef. func getTree(ref *github.Reference) (tree *github.Tree, err error) { // Create a tree with what to commit. entries := []github.TreeEntry{} // Load each file into the tree. for _, fileArg := range strings.Split(*sourceFiles, ",") { file, content, err := getFileContent(fileArg) if err != nil { return nil, err } entries = append(entries, github.TreeEntry{Path: github.String(file), Type: github.String("blob"), Content: github.String(string(content)), Mode: github.String("100644")}) } tree, _, err = client.Git.CreateTree(ctx, *sourceOwner, *sourceRepo, *ref.Object.SHA, entries) return tree, err } // getFileContent loads the local content of a file and return the target name // of the file in the target repository and its contents. func getFileContent(fileArg string) (targetName string, b []byte, err error) { var localFile string files := strings.Split(fileArg, ":") switch { case len(files) < 1: return "", nil, errors.New("empty `-files` parameter") case len(files) == 1: localFile = files[0] targetName = files[0] default: localFile = files[0] targetName = files[1] } b, err = ioutil.ReadFile(localFile) return targetName, b, err } // createCommit creates the commit in the given reference using the given tree. func pushCommit(ref *github.Reference, tree *github.Tree) (err error) { // Get the parent commit to attach the commit to. parent, _, err := client.Repositories.GetCommit(ctx, *sourceOwner, *sourceRepo, *ref.Object.SHA) if err != nil { return err } // This is not always populated, but is needed. parent.Commit.SHA = parent.SHA // Create the commit using the tree. date := time.Now() author := &github.CommitAuthor{Date: &date, Name: authorName, Email: authorEmail} commit := &github.Commit{Author: author, Message: commitMessage, Tree: tree, Parents: []github.Commit{*parent.Commit}} newCommit, _, err := client.Git.CreateCommit(ctx, *sourceOwner, *sourceRepo, commit) if err != nil { return err } // Attach the commit to the master branch. ref.Object.SHA = newCommit.SHA _, _, err = client.Git.UpdateRef(ctx, *sourceOwner, *sourceRepo, ref, false) return err } // createPR creates a pull request. Based on: https://godoc.org/github.com/google/go-github/github#example-PullRequestsService-Create func createPR() (err error) { if *prSubject == "" { return errors.New("missing `-pr-title` flag; skipping PR creation") } if *prRepoOwner != "" && *prRepoOwner != *sourceOwner { *commitBranch = fmt.Sprintf("%s:%s", *sourceOwner, *commitBranch) } else { prRepoOwner = sourceOwner } if *prRepo == "" { prRepo = sourceRepo } newPR := &github.NewPullRequest{ Title: prSubject, Head: commitBranch, Base: prBranch, Body: prDescription, MaintainerCanModify: github.Bool(true), } pr, _, err := client.PullRequests.Create(ctx, *prRepoOwner, *prRepo, newPR) if err != nil { return err } fmt.Printf("PR created: %s\n", pr.GetHTMLURL()) return nil } func main() { flag.Parse() token := os.Getenv("GITHUB_AUTH_TOKEN") if token == "" { log.Fatal("Unauthorized: No token present") } if *sourceOwner == "" || *sourceRepo == "" || *commitBranch == "" || *sourceFiles == "" || *authorName == "" || *authorEmail == "" { log.Fatal("You need to specify a non-empty value for the flags `-source-owner`, `-source-repo`, `-commit-branch`, `-files`, `-author-name` and `-author-email`") } ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) tc := oauth2.NewClient(ctx, ts) client = github.NewClient(tc) ref, err := getRef() if err != nil { log.Fatalf("Unable to get/create the commit reference: %s\n", err) } if ref == nil { log.Fatalf("No error where returned but the reference is nil") } tree, err := getTree(ref) if err != nil { log.Fatalf("Unable to create the tree based on the provided files: %s\n", err) } if err := pushCommit(ref, tree); err != nil { log.Fatalf("Unable to create the commit: %s\n", err) } if err := createPR(); err != nil { log.Fatalf("Error while creating the pull request: %s", err) } } go-github-28.1.1/example/migrations/000077500000000000000000000000001353501270500173005ustar00rootroot00000000000000go-github-28.1.1/example/migrations/main.go000066400000000000000000000017111353501270500205530ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // migrations demonstrates the functionality of // the user data migration API for the authenticated GitHub // user and lists all the user migrations. package main import ( "context" "fmt" "github.com/google/go-github/v28/github" "golang.org/x/oauth2" ) func fetchAllUserMigrations() ([]*github.UserMigration, error) { ctx := context.Background() ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: ""}, ) tc := oauth2.NewClient(ctx, ts) client := github.NewClient(tc) migrations, _, err := client.Migrations.ListUserMigrations(ctx) return migrations, err } func main() { migrations, err := fetchAllUserMigrations() if err != nil { fmt.Printf("Error %v\n", err) return } for i, m := range migrations { fmt.Printf("%v. %v", i+1, m.GetID()) } } go-github-28.1.1/example/newrepo/000077500000000000000000000000001353501270500166035ustar00rootroot00000000000000go-github-28.1.1/example/newrepo/main.go000066400000000000000000000025731353501270500200650ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // The newrepo command utilizes go-github as a cli tool for // creating new repositories. It takes an auth token as // an environment variable and creates the new repo under // the account affiliated with that token. package main import ( "context" "flag" "fmt" "log" "os" "github.com/google/go-github/v28/github" "golang.org/x/oauth2" ) var ( name = flag.String("name", "", "Name of repo to create in authenticated user's GitHub account.") description = flag.String("description", "", "Description of created repo.") private = flag.Bool("private", false, "Will created repo be private.") ) func main() { flag.Parse() token := os.Getenv("GITHUB_AUTH_TOKEN") if token == "" { log.Fatal("Unauthorized: No token present") } if *name == "" { log.Fatal("No name: New repos must be given a name") } ctx := context.Background() ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) tc := oauth2.NewClient(ctx, ts) client := github.NewClient(tc) r := &github.Repository{Name: name, Private: private, Description: description} repo, _, err := client.Repositories.Create(ctx, "", r) if err != nil { log.Fatal(err) } fmt.Printf("Successfully created new repo: %v\n", repo.GetName()) } go-github-28.1.1/example/simple/000077500000000000000000000000001353501270500164155ustar00rootroot00000000000000go-github-28.1.1/example/simple/main.go000066400000000000000000000020171353501270500176700ustar00rootroot00000000000000// Copyright 2017 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. // The simple command demonstrates a simple functionality which // prompts the user for a GitHub username and lists all the public // organization memberships of the specified username. package main import ( "context" "fmt" "github.com/google/go-github/v28/github" ) // Fetch all the public organizations' membership of a user. // func FetchOrganizations(username string) ([]*github.Organization, error) { client := github.NewClient(nil) orgs, _, err := client.Organizations.List(context.Background(), username, nil) return orgs, err } func main() { var username string fmt.Print("Enter GitHub username: ") fmt.Scanf("%s", &username) organizations, err := FetchOrganizations(username) if err != nil { fmt.Printf("Error: %v\n", err) return } for i, organization := range organizations { fmt.Printf("%v. %v\n", i+1, organization.GetLogin()) } } go-github-28.1.1/github/000077500000000000000000000000001353501270500147535ustar00rootroot00000000000000go-github-28.1.1/github/activity.go000066400000000000000000000054351353501270500171450ustar00rootroot00000000000000// 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" // ActivityService handles communication with the activity related // methods of the GitHub API. // // GitHub API docs: https://developer.github.com/v3/activity/ type ActivityService service // FeedLink represents a link to a related resource. type FeedLink struct { HRef *string `json:"href,omitempty"` Type *string `json:"type,omitempty"` } // Feeds represents timeline resources in Atom format. type Feeds struct { TimelineURL *string `json:"timeline_url,omitempty"` UserURL *string `json:"user_url,omitempty"` CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"` CurrentUserURL *string `json:"current_user_url,omitempty"` CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"` CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"` CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"` Links *struct { Timeline *FeedLink `json:"timeline,omitempty"` User *FeedLink `json:"user,omitempty"` CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` CurrentUser *FeedLink `json:"current_user,omitempty"` CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` CurrentUserOrganizations []FeedLink `json:"current_user_organizations,omitempty"` } `json:"_links,omitempty"` } // ListFeeds lists all the feeds available to the authenticated user. // // GitHub provides several timeline resources in Atom format: // Timeline: The GitHub global public timeline // User: The public timeline for any user, using URI template // Current user public: The public timeline for the authenticated user // Current user: The private timeline for the authenticated user // Current user actor: The private timeline for activity created by the // authenticated user // Current user organizations: The private timeline for the organizations // the authenticated user is a member of. // // Note: Private feeds are only returned when authenticating via Basic Auth // since current feed URIs use the older, non revocable auth tokens. func (s *ActivityService) ListFeeds(ctx context.Context) (*Feeds, *Response, error) { req, err := s.client.NewRequest("GET", "feeds", nil) if err != nil { return nil, nil, err } f := &Feeds{} resp, err := s.client.Do(ctx, req, f) if err != nil { return nil, resp, err } return f, resp, nil } go-github-28.1.1/github/activity_events.go000066400000000000000000000134531353501270500205300ustar00rootroot00000000000000// 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, opt *ListOptions) ([]*Event, *Response, error) { u, err := addOptions("events", opt) 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, opt *ListOptions) ([]*Event, *Response, error) { u := fmt.Sprintf("repos/%v/%v/events", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var events []*Event resp, err := s.client.Do(ctx, req, &events) if err != nil { return nil, resp, err } return events, resp, nil } // ListIssueEventsForRepository lists issue events for a repository. // // GitHub API docs: https://developer.github.com/v3/activity/events/#list-issue-events-for-a-repository func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var events []*IssueEvent resp, err := s.client.Do(ctx, req, &events) if err != nil { return nil, resp, err } return events, resp, nil } // 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, opt *ListOptions) ([]*Event, *Response, error) { u := fmt.Sprintf("networks/%v/%v/events", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } 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, opt *ListOptions) ([]*Event, *Response, error) { u := fmt.Sprintf("orgs/%v/events", org) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } 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, opt *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, opt) 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, opt *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, opt) 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, opt *ListOptions) ([]*Event, *Response, error) { u := fmt.Sprintf("users/%v/events/orgs/%v", user, org) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var events []*Event resp, err := s.client.Do(ctx, req, &events) if err != nil { return nil, resp, err } return events, resp, nil } go-github-28.1.1/github/activity_events_test.go000066400000000000000000000251211353501270500215620ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestActivityService_ListEvents(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/events", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`) }) opt := &ListOptions{Page: 2} events, _, err := client.Activity.ListEvents(context.Background(), opt) if err != nil { t.Errorf("Activities.ListEvents returned error: %v", err) } want := []*Event{{ID: String("1")}, {ID: String("2")}} if !reflect.DeepEqual(events, want) { t.Errorf("Activities.ListEvents returned %+v, want %+v", events, want) } } func TestActivityService_ListRepositoryEvents(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/events", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`) }) opt := &ListOptions{Page: 2} events, _, err := client.Activity.ListRepositoryEvents(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Activities.ListRepositoryEvents returned error: %v", err) } want := []*Event{{ID: String("1")}, {ID: String("2")}} if !reflect.DeepEqual(events, want) { t.Errorf("Activities.ListRepositoryEvents returned %+v, want %+v", events, want) } } func TestActivityService_ListRepositoryEvents_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Activity.ListRepositoryEvents(context.Background(), "%", "%", nil) testURLParseError(t, err) } func TestActivityService_ListIssueEventsForRepository(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/events", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":1},{"id":2}]`) }) opt := &ListOptions{Page: 2} events, _, err := client.Activity.ListIssueEventsForRepository(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Activities.ListIssueEventsForRepository returned error: %v", err) } want := []*IssueEvent{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(events, want) { t.Errorf("Activities.ListIssueEventsForRepository returned %+v, want %+v", events, want) } } func TestActivityService_ListIssueEventsForRepository_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Activity.ListIssueEventsForRepository(context.Background(), "%", "%", nil) testURLParseError(t, err) } func TestActivityService_ListEventsForRepoNetwork(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/networks/o/r/events", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`) }) opt := &ListOptions{Page: 2} events, _, err := client.Activity.ListEventsForRepoNetwork(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Activities.ListEventsForRepoNetwork returned error: %v", err) } want := []*Event{{ID: String("1")}, {ID: String("2")}} if !reflect.DeepEqual(events, want) { t.Errorf("Activities.ListEventsForRepoNetwork returned %+v, want %+v", events, want) } } func TestActivityService_ListEventsForRepoNetwork_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Activity.ListEventsForRepoNetwork(context.Background(), "%", "%", nil) testURLParseError(t, err) } func TestActivityService_ListEventsForOrganization(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/events", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`) }) opt := &ListOptions{Page: 2} events, _, err := client.Activity.ListEventsForOrganization(context.Background(), "o", opt) if err != nil { t.Errorf("Activities.ListEventsForOrganization returned error: %v", err) } want := []*Event{{ID: String("1")}, {ID: String("2")}} if !reflect.DeepEqual(events, want) { t.Errorf("Activities.ListEventsForOrganization returned %+v, want %+v", events, want) } } func TestActivityService_ListEventsForOrganization_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Activity.ListEventsForOrganization(context.Background(), "%", nil) testURLParseError(t, err) } func TestActivityService_ListEventsPerformedByUser_all(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/events", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`) }) opt := &ListOptions{Page: 2} events, _, err := client.Activity.ListEventsPerformedByUser(context.Background(), "u", false, opt) if err != nil { t.Errorf("Events.ListPerformedByUser returned error: %v", err) } want := []*Event{{ID: String("1")}, {ID: String("2")}} if !reflect.DeepEqual(events, want) { t.Errorf("Events.ListPerformedByUser returned %+v, want %+v", events, want) } } func TestActivityService_ListEventsPerformedByUser_publicOnly(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/events/public", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`) }) events, _, err := client.Activity.ListEventsPerformedByUser(context.Background(), "u", true, nil) if err != nil { t.Errorf("Events.ListPerformedByUser returned error: %v", err) } want := []*Event{{ID: String("1")}, {ID: String("2")}} if !reflect.DeepEqual(events, want) { t.Errorf("Events.ListPerformedByUser returned %+v, want %+v", events, want) } } func TestActivityService_ListEventsPerformedByUser_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Activity.ListEventsPerformedByUser(context.Background(), "%", false, nil) testURLParseError(t, err) } func TestActivityService_ListEventsReceivedByUser_all(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/received_events", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`) }) opt := &ListOptions{Page: 2} events, _, err := client.Activity.ListEventsReceivedByUser(context.Background(), "u", false, opt) if err != nil { t.Errorf("Events.ListReceivedByUser returned error: %v", err) } want := []*Event{{ID: String("1")}, {ID: String("2")}} if !reflect.DeepEqual(events, want) { t.Errorf("Events.ListReceivedUser returned %+v, want %+v", events, want) } } func TestActivityService_ListEventsReceivedByUser_publicOnly(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/received_events/public", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`) }) events, _, err := client.Activity.ListEventsReceivedByUser(context.Background(), "u", true, nil) if err != nil { t.Errorf("Events.ListReceivedByUser returned error: %v", err) } want := []*Event{{ID: String("1")}, {ID: String("2")}} if !reflect.DeepEqual(events, want) { t.Errorf("Events.ListReceivedByUser returned %+v, want %+v", events, want) } } func TestActivityService_ListEventsReceivedByUser_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Activity.ListEventsReceivedByUser(context.Background(), "%", false, nil) testURLParseError(t, err) } func TestActivityService_ListUserEventsForOrganization(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/events/orgs/o", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":"1"},{"id":"2"}]`) }) opt := &ListOptions{Page: 2} events, _, err := client.Activity.ListUserEventsForOrganization(context.Background(), "o", "u", opt) if err != nil { t.Errorf("Activities.ListUserEventsForOrganization returned error: %v", err) } want := []*Event{{ID: String("1")}, {ID: String("2")}} if !reflect.DeepEqual(events, want) { t.Errorf("Activities.ListUserEventsForOrganization returned %+v, want %+v", events, want) } } func TestActivityService_EventParsePayload_typed(t *testing.T) { raw := []byte(`{"type": "PushEvent","payload":{"push_id": 1}}`) var event *Event if err := json.Unmarshal(raw, &event); err != nil { t.Fatalf("Unmarshal Event returned error: %v", err) } want := &PushEvent{PushID: Int64(1)} got, err := event.ParsePayload() if err != nil { t.Fatalf("ParsePayload returned unexpected error: %v", err) } if !reflect.DeepEqual(got, want) { t.Errorf("Event.ParsePayload returned %+v, want %+v", got, want) } } // TestEvent_Payload_untyped checks that unrecognized events are parsed to an // interface{} value (instead of being discarded or throwing an error), for // forward compatibility with new event types. func TestActivityService_EventParsePayload_untyped(t *testing.T) { raw := []byte(`{"type": "UnrecognizedEvent","payload":{"field": "val"}}`) var event *Event if err := json.Unmarshal(raw, &event); err != nil { t.Fatalf("Unmarshal Event returned error: %v", err) } want := map[string]interface{}{"field": "val"} got, err := event.ParsePayload() if err != nil { t.Fatalf("ParsePayload returned unexpected error: %v", err) } if !reflect.DeepEqual(got, want) { t.Errorf("Event.ParsePayload returned %+v, want %+v", got, want) } } func TestActivityService_EventParsePayload_installation(t *testing.T) { raw := []byte(`{"type": "PullRequestEvent","payload":{"installation":{"id":1}}}`) var event *Event if err := json.Unmarshal(raw, &event); err != nil { t.Fatalf("Unmarshal Event returned error: %v", err) } want := &PullRequestEvent{Installation: &Installation{ID: Int64(1)}} got, err := event.ParsePayload() if err != nil { t.Fatalf("ParsePayload returned unexpected error: %v", err) } if !reflect.DeepEqual(got, want) { t.Errorf("Event.ParsePayload returned %+v, want %+v", got, want) } } go-github-28.1.1/github/activity_notifications.go000066400000000000000000000155241353501270500220760ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "time" ) // Notification identifies a GitHub notification for a user. type Notification struct { ID *string `json:"id,omitempty"` Repository *Repository `json:"repository,omitempty"` Subject *NotificationSubject `json:"subject,omitempty"` // Reason identifies the event that triggered the notification. // // GitHub API docs: https://developer.github.com/v3/activity/notifications/#notification-reasons Reason *string `json:"reason,omitempty"` Unread *bool `json:"unread,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` LastReadAt *time.Time `json:"last_read_at,omitempty"` URL *string `json:"url,omitempty"` } // NotificationSubject identifies the subject of a notification. type NotificationSubject struct { Title *string `json:"title,omitempty"` URL *string `json:"url,omitempty"` LatestCommentURL *string `json:"latest_comment_url,omitempty"` Type *string `json:"type,omitempty"` } // NotificationListOptions specifies the optional parameters to the // ActivityService.ListNotifications method. type NotificationListOptions struct { All bool `url:"all,omitempty"` Participating bool `url:"participating,omitempty"` Since time.Time `url:"since,omitempty"` Before time.Time `url:"before,omitempty"` ListOptions } // ListNotifications lists all notifications for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications func (s *ActivityService) ListNotifications(ctx context.Context, opt *NotificationListOptions) ([]*Notification, *Response, error) { u := fmt.Sprintf("notifications") u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var notifications []*Notification resp, err := s.client.Do(ctx, req, ¬ifications) if err != nil { return nil, resp, err } return notifications, resp, nil } // 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 func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner, repo string, opt *NotificationListOptions) ([]*Notification, *Response, error) { u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var notifications []*Notification resp, err := s.client.Do(ctx, req, ¬ifications) if err != nil { return nil, resp, err } return notifications, resp, nil } type markReadOptions struct { LastReadAt time.Time `json:"last_read_at,omitempty"` } // MarkNotificationsRead marks all notifications up to lastRead as read. // // GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-as-read func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead time.Time) (*Response, error) { opts := &markReadOptions{ LastReadAt: lastRead, } req, err := s.client.NewRequest("PUT", "notifications", opts) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // 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 func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead time.Time) (*Response, error) { opts := &markReadOptions{ LastReadAt: lastRead, } u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) req, err := s.client.NewRequest("PUT", u, opts) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // GetThread gets the specified notification thread. // // GitHub API docs: https://developer.github.com/v3/activity/notifications/#view-a-single-thread func (s *ActivityService) GetThread(ctx context.Context, id string) (*Notification, *Response, error) { u := fmt.Sprintf("notifications/threads/%v", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } notification := new(Notification) resp, err := s.client.Do(ctx, req, notification) if err != nil { return nil, resp, err } return notification, resp, nil } // MarkThreadRead marks the specified thread as read. // // GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-a-thread-as-read func (s *ActivityService) MarkThreadRead(ctx context.Context, id string) (*Response, error) { u := fmt.Sprintf("notifications/threads/%v", id) req, err := s.client.NewRequest("PATCH", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // 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 func (s *ActivityService) GetThreadSubscription(ctx context.Context, id string) (*Subscription, *Response, error) { u := fmt.Sprintf("notifications/threads/%v/subscription", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } sub := new(Subscription) resp, err := s.client.Do(ctx, req, sub) if err != nil { return nil, resp, err } return sub, resp, nil } // SetThreadSubscription sets the subscription for the specified thread for the // authenticated user. // // GitHub API docs: https://developer.github.com/v3/activity/notifications/#set-a-thread-subscription func (s *ActivityService) SetThreadSubscription(ctx context.Context, id string, subscription *Subscription) (*Subscription, *Response, error) { u := fmt.Sprintf("notifications/threads/%v/subscription", id) req, err := s.client.NewRequest("PUT", u, subscription) if err != nil { return nil, nil, err } sub := new(Subscription) resp, err := s.client.Do(ctx, req, sub) if err != nil { return nil, resp, err } return sub, resp, nil } // DeleteThreadSubscription deletes the subscription for the specified thread // for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/activity/notifications/#delete-a-thread-subscription func (s *ActivityService) DeleteThreadSubscription(ctx context.Context, id string) (*Response, error) { u := fmt.Sprintf("notifications/threads/%v/subscription", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/activity_notifications_test.go000066400000000000000000000142201353501270500231250ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" "time" ) func TestActivityService_ListNotification(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/notifications", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "all": "true", "participating": "true", "since": "2006-01-02T15:04:05Z", "before": "2007-03-04T15:04:05Z", }) fmt.Fprint(w, `[{"id":"1", "subject":{"title":"t"}}]`) }) opt := &NotificationListOptions{ All: true, Participating: true, Since: time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC), Before: time.Date(2007, time.March, 04, 15, 04, 05, 0, time.UTC), } notifications, _, err := client.Activity.ListNotifications(context.Background(), opt) if err != nil { t.Errorf("Activity.ListNotifications returned error: %v", err) } want := []*Notification{{ID: String("1"), Subject: &NotificationSubject{Title: String("t")}}} if !reflect.DeepEqual(notifications, want) { t.Errorf("Activity.ListNotifications returned %+v, want %+v", notifications, want) } } func TestActivityService_ListRepositoryNotification(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/notifications", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":"1"}]`) }) notifications, _, err := client.Activity.ListRepositoryNotifications(context.Background(), "o", "r", nil) if err != nil { t.Errorf("Activity.ListRepositoryNotifications returned error: %v", err) } want := []*Notification{{ID: String("1")}} if !reflect.DeepEqual(notifications, want) { t.Errorf("Activity.ListRepositoryNotifications returned %+v, want %+v", notifications, want) } } func TestActivityService_MarkNotificationsRead(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/notifications", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Content-Type", "application/json") testBody(t, r, `{"last_read_at":"2006-01-02T15:04:05Z"}`+"\n") w.WriteHeader(http.StatusResetContent) }) _, err := client.Activity.MarkNotificationsRead(context.Background(), time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)) if err != nil { t.Errorf("Activity.MarkNotificationsRead returned error: %v", err) } } func TestActivityService_MarkRepositoryNotificationsRead(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/notifications", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Content-Type", "application/json") testBody(t, r, `{"last_read_at":"2006-01-02T15:04:05Z"}`+"\n") w.WriteHeader(http.StatusResetContent) }) _, err := client.Activity.MarkRepositoryNotificationsRead(context.Background(), "o", "r", time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)) if err != nil { t.Errorf("Activity.MarkRepositoryNotificationsRead returned error: %v", err) } } func TestActivityService_GetThread(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/notifications/threads/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":"1"}`) }) notification, _, err := client.Activity.GetThread(context.Background(), "1") if err != nil { t.Errorf("Activity.GetThread returned error: %v", err) } want := &Notification{ID: String("1")} if !reflect.DeepEqual(notification, want) { t.Errorf("Activity.GetThread returned %+v, want %+v", notification, want) } } func TestActivityService_MarkThreadRead(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/notifications/threads/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") w.WriteHeader(http.StatusResetContent) }) _, err := client.Activity.MarkThreadRead(context.Background(), "1") if err != nil { t.Errorf("Activity.MarkThreadRead returned error: %v", err) } } func TestActivityService_GetThreadSubscription(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/notifications/threads/1/subscription", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"subscribed":true}`) }) sub, _, err := client.Activity.GetThreadSubscription(context.Background(), "1") if err != nil { t.Errorf("Activity.GetThreadSubscription returned error: %v", err) } want := &Subscription{Subscribed: Bool(true)} if !reflect.DeepEqual(sub, want) { t.Errorf("Activity.GetThreadSubscription returned %+v, want %+v", sub, want) } } func TestActivityService_SetThreadSubscription(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Subscription{Subscribed: Bool(true)} mux.HandleFunc("/notifications/threads/1/subscription", func(w http.ResponseWriter, r *http.Request) { v := new(Subscription) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"ignored":true}`) }) sub, _, err := client.Activity.SetThreadSubscription(context.Background(), "1", input) if err != nil { t.Errorf("Activity.SetThreadSubscription returned error: %v", err) } want := &Subscription{Ignored: Bool(true)} if !reflect.DeepEqual(sub, want) { t.Errorf("Activity.SetThreadSubscription returned %+v, want %+v", sub, want) } } func TestActivityService_DeleteThreadSubscription(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/notifications/threads/1/subscription", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Activity.DeleteThreadSubscription(context.Background(), "1") if err != nil { t.Errorf("Activity.DeleteThreadSubscription returned error: %v", err) } } go-github-28.1.1/github/activity_star.go000066400000000000000000000103321353501270500201660ustar00rootroot00000000000000// 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" "strings" ) // StarredRepository is returned by ListStarred. type StarredRepository struct { StarredAt *Timestamp `json:"starred_at,omitempty"` Repository *Repository `json:"repo,omitempty"` } // Stargazer represents a user that has starred a repository. type Stargazer struct { StarredAt *Timestamp `json:"starred_at,omitempty"` User *User `json:"user,omitempty"` } // ListStargazers lists people who have starred the specified repo. // // GitHub API docs: https://developer.github.com/v3/activity/starring/#list-stargazers func (s *ActivityService) ListStargazers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Stargazer, *Response, error) { u := fmt.Sprintf("repos/%s/%s/stargazers", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeStarringPreview) var stargazers []*Stargazer resp, err := s.client.Do(ctx, req, &stargazers) if err != nil { return nil, resp, err } return stargazers, resp, nil } // ActivityListStarredOptions specifies the optional parameters to the // ActivityService.ListStarred method. type ActivityListStarredOptions struct { // How to sort the repository list. Possible values are: created, updated, // pushed, full_name. Default is "full_name". Sort string `url:"sort,omitempty"` // Direction in which to sort repositories. Possible values are: asc, desc. // Default is "asc" when sort is "full_name", otherwise default is "desc". Direction string `url:"direction,omitempty"` ListOptions } // 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 func (s *ActivityService) ListStarred(ctx context.Context, user string, opt *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/starred", user) } else { u = "user/starred" } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when APIs fully launch acceptHeaders := []string{mediaTypeStarringPreview, mediaTypeTopicsPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var repos []*StarredRepository resp, err := s.client.Do(ctx, req, &repos) if err != nil { return nil, resp, err } return repos, resp, nil } // 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 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) if err != nil { return false, nil, err } resp, err := s.client.Do(ctx, req, nil) starred, err := parseBoolResponse(err) return starred, resp, err } // Star a repository as the authenticated user. // // GitHub API docs: https://developer.github.com/v3/activity/starring/#star-a-repository 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) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // Unstar a repository as the authenticated user. // // GitHub API docs: https://developer.github.com/v3/activity/starring/#unstar-a-repository 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) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/activity_star_test.go000066400000000000000000000130111353501270500212220ustar00rootroot00000000000000// 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" "net/http" "reflect" "strings" "testing" "time" ) func TestActivityService_ListStargazers(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/stargazers", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeStarringPreview) testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"starred_at":"2002-02-10T15:30:00Z","user":{"id":1}}]`) }) stargazers, _, err := client.Activity.ListStargazers(context.Background(), "o", "r", &ListOptions{Page: 2}) if err != nil { t.Errorf("Activity.ListStargazers returned error: %v", err) } want := []*Stargazer{{StarredAt: &Timestamp{time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)}, User: &User{ID: Int64(1)}}} if !reflect.DeepEqual(stargazers, want) { t.Errorf("Activity.ListStargazers returned %+v, want %+v", stargazers, want) } } func TestActivityService_ListStarred_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/starred", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join([]string{mediaTypeStarringPreview, mediaTypeTopicsPreview}, ", ")) fmt.Fprint(w, `[{"starred_at":"2002-02-10T15:30:00Z","repo":{"id":1}}]`) }) repos, _, err := client.Activity.ListStarred(context.Background(), "", nil) if err != nil { t.Errorf("Activity.ListStarred returned error: %v", err) } want := []*StarredRepository{{StarredAt: &Timestamp{time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)}, Repository: &Repository{ID: Int64(1)}}} if !reflect.DeepEqual(repos, want) { t.Errorf("Activity.ListStarred returned %+v, want %+v", repos, want) } } func TestActivityService_ListStarred_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/starred", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join([]string{mediaTypeStarringPreview, mediaTypeTopicsPreview}, ", ")) testFormValues(t, r, values{ "sort": "created", "direction": "asc", "page": "2", }) fmt.Fprint(w, `[{"starred_at":"2002-02-10T15:30:00Z","repo":{"id":2}}]`) }) opt := &ActivityListStarredOptions{"created", "asc", ListOptions{Page: 2}} repos, _, err := client.Activity.ListStarred(context.Background(), "u", opt) if err != nil { t.Errorf("Activity.ListStarred returned error: %v", err) } want := []*StarredRepository{{StarredAt: &Timestamp{time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)}, Repository: &Repository{ID: Int64(2)}}} if !reflect.DeepEqual(repos, want) { t.Errorf("Activity.ListStarred returned %+v, want %+v", repos, want) } } func TestActivityService_ListStarred_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Activity.ListStarred(context.Background(), "%", nil) testURLParseError(t, err) } func TestActivityService_IsStarred_hasStar(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/starred/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNoContent) }) star, _, err := client.Activity.IsStarred(context.Background(), "o", "r") if err != nil { t.Errorf("Activity.IsStarred returned error: %v", err) } if want := true; star != want { t.Errorf("Activity.IsStarred returned %+v, want %+v", star, want) } } func TestActivityService_IsStarred_noStar(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/starred/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) star, _, err := client.Activity.IsStarred(context.Background(), "o", "r") if err != nil { t.Errorf("Activity.IsStarred returned error: %v", err) } if want := false; star != want { t.Errorf("Activity.IsStarred returned %+v, want %+v", star, want) } } func TestActivityService_IsStarred_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Activity.IsStarred(context.Background(), "%", "%") testURLParseError(t, err) } func TestActivityService_Star(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/starred/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") }) _, err := client.Activity.Star(context.Background(), "o", "r") if err != nil { t.Errorf("Activity.Star returned error: %v", err) } } func TestActivityService_Star_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Activity.Star(context.Background(), "%", "%") testURLParseError(t, err) } func TestActivityService_Unstar(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/starred/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Activity.Unstar(context.Background(), "o", "r") if err != nil { t.Errorf("Activity.Unstar returned error: %v", err) } } func TestActivityService_Unstar_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Activity.Unstar(context.Background(), "%", "%") testURLParseError(t, err) } go-github-28.1.1/github/activity_test.go000066400000000000000000000120161353501270500201750ustar00rootroot00000000000000// 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" "net/http" "reflect" "testing" "time" ) func TestActivityService_List(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/feeds", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusOK) w.Write(feedsJSON) }) ctx := context.Background() got, _, err := client.Activity.ListFeeds(ctx) if err != nil { t.Errorf("Activity.ListFeeds returned error: %v", err) } if want := wantFeeds; !reflect.DeepEqual(got, want) { t.Errorf("Activity.ListFeeds = %+v, want %+v", got, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Activity.ListFeeds(ctx) if got != nil { t.Errorf("client.BaseURL.Path='' ListFeeds = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' ListFeeds resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' ListFeeds err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Activity.ListFeeds(ctx) if got != nil { t.Errorf("rate.Reset.Time > now ListFeeds = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now ListFeeds resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now ListFeeds err = nil, want error") } } var feedsJSON = []byte(`{ "timeline_url": "https://github.com/timeline", "user_url": "https://github.com/{user}", "current_user_public_url": "https://github.com/defunkt", "current_user_url": "https://github.com/defunkt.private?token=abc123", "current_user_actor_url": "https://github.com/defunkt.private.actor?token=abc123", "current_user_organization_url": "", "current_user_organization_urls": [ "https://github.com/organizations/github/defunkt.private.atom?token=abc123" ], "_links": { "timeline": { "href": "https://github.com/timeline", "type": "application/atom+xml" }, "user": { "href": "https://github.com/{user}", "type": "application/atom+xml" }, "current_user_public": { "href": "https://github.com/defunkt", "type": "application/atom+xml" }, "current_user": { "href": "https://github.com/defunkt.private?token=abc123", "type": "application/atom+xml" }, "current_user_actor": { "href": "https://github.com/defunkt.private.actor?token=abc123", "type": "application/atom+xml" }, "current_user_organization": { "href": "", "type": "" }, "current_user_organizations": [ { "href": "https://github.com/organizations/github/defunkt.private.atom?token=abc123", "type": "application/atom+xml" } ] } }`) var wantFeeds = &Feeds{ TimelineURL: String("https://github.com/timeline"), UserURL: String("https://github.com/{user}"), CurrentUserPublicURL: String("https://github.com/defunkt"), CurrentUserURL: String("https://github.com/defunkt.private?token=abc123"), CurrentUserActorURL: String("https://github.com/defunkt.private.actor?token=abc123"), CurrentUserOrganizationURL: String(""), CurrentUserOrganizationURLs: []string{ "https://github.com/organizations/github/defunkt.private.atom?token=abc123", }, Links: &struct { Timeline *FeedLink `json:"timeline,omitempty"` User *FeedLink `json:"user,omitempty"` CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` CurrentUser *FeedLink `json:"current_user,omitempty"` CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` CurrentUserOrganizations []FeedLink `json:"current_user_organizations,omitempty"` }{ Timeline: &FeedLink{ HRef: String("https://github.com/timeline"), Type: String("application/atom+xml"), }, User: &FeedLink{ HRef: String("https://github.com/{user}"), Type: String("application/atom+xml"), }, CurrentUserPublic: &FeedLink{ HRef: String("https://github.com/defunkt"), Type: String("application/atom+xml"), }, CurrentUser: &FeedLink{ HRef: String("https://github.com/defunkt.private?token=abc123"), Type: String("application/atom+xml"), }, CurrentUserActor: &FeedLink{ HRef: String("https://github.com/defunkt.private.actor?token=abc123"), Type: String("application/atom+xml"), }, CurrentUserOrganization: &FeedLink{ HRef: String(""), Type: String(""), }, CurrentUserOrganizations: []FeedLink{ { HRef: String("https://github.com/organizations/github/defunkt.private.atom?token=abc123"), Type: String("application/atom+xml"), }, }, }, } go-github-28.1.1/github/activity_watching.go000066400000000000000000000110011353501270500210130ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" ) // Subscription identifies a repository or thread subscription. type Subscription struct { Subscribed *bool `json:"subscribed,omitempty"` Ignored *bool `json:"ignored,omitempty"` Reason *string `json:"reason,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` URL *string `json:"url,omitempty"` // only populated for repository subscriptions RepositoryURL *string `json:"repository_url,omitempty"` // only populated for thread subscriptions ThreadURL *string `json:"thread_url,omitempty"` } // ListWatchers lists watchers of a particular repo. // // GitHub API docs: https://developer.github.com/v3/activity/watching/#list-watchers func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) { u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var watchers []*User resp, err := s.client.Do(ctx, req, &watchers) if err != nil { return nil, resp, err } return watchers, resp, nil } // 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 func (s *ActivityService) ListWatched(ctx context.Context, user string, opt *ListOptions) ([]*Repository, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/subscriptions", user) } else { u = "user/subscriptions" } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var watched []*Repository resp, err := s.client.Do(ctx, req, &watched) if err != nil { return nil, resp, err } return watched, resp, nil } // GetRepositorySubscription returns the subscription for the specified // repository for the authenticated user. If the authenticated user is not // watching the repository, a nil Subscription is returned. // // GitHub API docs: https://developer.github.com/v3/activity/watching/#get-a-repository-subscription func (s *ActivityService) GetRepositorySubscription(ctx context.Context, owner, repo string) (*Subscription, *Response, error) { u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } sub := new(Subscription) resp, err := s.client.Do(ctx, req, sub) if err != nil { // if it's just a 404, don't return that as an error _, err = parseBoolResponse(err) return nil, resp, err } return sub, resp, nil } // SetRepositorySubscription sets the subscription for the specified repository // for the authenticated user. // // To watch a repository, set subscription.Subscribed to true. // To ignore notifications made within a repository, set subscription.Ignored to true. // To stop watching a repository, use DeleteRepositorySubscription. // // GitHub API docs: https://developer.github.com/v3/activity/watching/#set-a-repository-subscription func (s *ActivityService) SetRepositorySubscription(ctx context.Context, owner, repo string, subscription *Subscription) (*Subscription, *Response, error) { u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) req, err := s.client.NewRequest("PUT", u, subscription) if err != nil { return nil, nil, err } sub := new(Subscription) resp, err := s.client.Do(ctx, req, sub) if err != nil { return nil, resp, err } return sub, resp, nil } // DeleteRepositorySubscription deletes the subscription for the specified // repository for the authenticated user. // // This is used to stop watching a repository. To control whether or not to // receive notifications from a repository, use SetRepositorySubscription. // // GitHub API docs: https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription func (s *ActivityService) DeleteRepositorySubscription(ctx context.Context, owner, repo string) (*Response, error) { u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/activity_watching_test.go000066400000000000000000000122241353501270500220620ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestActivityService_ListWatchers(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/subscribers", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) watchers, _, err := client.Activity.ListWatchers(context.Background(), "o", "r", &ListOptions{Page: 2}) if err != nil { t.Errorf("Activity.ListWatchers returned error: %v", err) } want := []*User{{ID: Int64(1)}} if !reflect.DeepEqual(watchers, want) { t.Errorf("Activity.ListWatchers returned %+v, want %+v", watchers, want) } } func TestActivityService_ListWatched_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/subscriptions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) watched, _, err := client.Activity.ListWatched(context.Background(), "", &ListOptions{Page: 2}) if err != nil { t.Errorf("Activity.ListWatched returned error: %v", err) } want := []*Repository{{ID: Int64(1)}} if !reflect.DeepEqual(watched, want) { t.Errorf("Activity.ListWatched returned %+v, want %+v", watched, want) } } func TestActivityService_ListWatched_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/subscriptions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) watched, _, err := client.Activity.ListWatched(context.Background(), "u", &ListOptions{Page: 2}) if err != nil { t.Errorf("Activity.ListWatched returned error: %v", err) } want := []*Repository{{ID: Int64(1)}} if !reflect.DeepEqual(watched, want) { t.Errorf("Activity.ListWatched returned %+v, want %+v", watched, want) } } func TestActivityService_GetRepositorySubscription_true(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"subscribed":true}`) }) sub, _, err := client.Activity.GetRepositorySubscription(context.Background(), "o", "r") if err != nil { t.Errorf("Activity.GetRepositorySubscription returned error: %v", err) } want := &Subscription{Subscribed: Bool(true)} if !reflect.DeepEqual(sub, want) { t.Errorf("Activity.GetRepositorySubscription returned %+v, want %+v", sub, want) } } func TestActivityService_GetRepositorySubscription_false(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) sub, _, err := client.Activity.GetRepositorySubscription(context.Background(), "o", "r") if err != nil { t.Errorf("Activity.GetRepositorySubscription returned error: %v", err) } var want *Subscription if !reflect.DeepEqual(sub, want) { t.Errorf("Activity.GetRepositorySubscription returned %+v, want %+v", sub, want) } } func TestActivityService_GetRepositorySubscription_error(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusBadRequest) }) _, _, err := client.Activity.GetRepositorySubscription(context.Background(), "o", "r") if err == nil { t.Errorf("Expected HTTP 400 response") } } func TestActivityService_SetRepositorySubscription(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Subscription{Subscribed: Bool(true)} mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) { v := new(Subscription) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"ignored":true}`) }) sub, _, err := client.Activity.SetRepositorySubscription(context.Background(), "o", "r", input) if err != nil { t.Errorf("Activity.SetRepositorySubscription returned error: %v", err) } want := &Subscription{Ignored: Bool(true)} if !reflect.DeepEqual(sub, want) { t.Errorf("Activity.SetRepositorySubscription returned %+v, want %+v", sub, want) } } func TestActivityService_DeleteRepositorySubscription(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Activity.DeleteRepositorySubscription(context.Background(), "o", "r") if err != nil { t.Errorf("Activity.DeleteRepositorySubscription returned error: %v", err) } } go-github-28.1.1/github/admin.go000066400000000000000000000066621353501270500164040ustar00rootroot00000000000000// 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" ) // AdminService handles communication with the admin related methods of the // GitHub API. These API routes are normally only accessible for GitHub // Enterprise installations. // // GitHub API docs: https://developer.github.com/v3/enterprise/ type AdminService service // TeamLDAPMapping represents the mapping between a GitHub team and an LDAP group. type TeamLDAPMapping struct { ID *int64 `json:"id,omitempty"` LDAPDN *string `json:"ldap_dn,omitempty"` URL *string `json:"url,omitempty"` Name *string `json:"name,omitempty"` Slug *string `json:"slug,omitempty"` Description *string `json:"description,omitempty"` Privacy *string `json:"privacy,omitempty"` Permission *string `json:"permission,omitempty"` MembersURL *string `json:"members_url,omitempty"` RepositoriesURL *string `json:"repositories_url,omitempty"` } func (m TeamLDAPMapping) String() string { return Stringify(m) } // UserLDAPMapping represents the mapping between a GitHub user and an LDAP user. type UserLDAPMapping struct { ID *int64 `json:"id,omitempty"` LDAPDN *string `json:"ldap_dn,omitempty"` Login *string `json:"login,omitempty"` AvatarURL *string `json:"avatar_url,omitempty"` GravatarID *string `json:"gravatar_id,omitempty"` Type *string `json:"type,omitempty"` SiteAdmin *bool `json:"site_admin,omitempty"` URL *string `json:"url,omitempty"` EventsURL *string `json:"events_url,omitempty"` FollowingURL *string `json:"following_url,omitempty"` FollowersURL *string `json:"followers_url,omitempty"` GistsURL *string `json:"gists_url,omitempty"` OrganizationsURL *string `json:"organizations_url,omitempty"` ReceivedEventsURL *string `json:"received_events_url,omitempty"` ReposURL *string `json:"repos_url,omitempty"` StarredURL *string `json:"starred_url,omitempty"` SubscriptionsURL *string `json:"subscriptions_url,omitempty"` } func (m UserLDAPMapping) String() string { return Stringify(m) } // UpdateUserLDAPMapping updates the mapping between a GitHub user and an LDAP user. // // GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-user func (s *AdminService) UpdateUserLDAPMapping(ctx context.Context, user string, mapping *UserLDAPMapping) (*UserLDAPMapping, *Response, error) { u := fmt.Sprintf("admin/ldap/users/%v/mapping", user) req, err := s.client.NewRequest("PATCH", u, mapping) if err != nil { return nil, nil, err } m := new(UserLDAPMapping) resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } // UpdateTeamLDAPMapping updates the mapping between a GitHub team and an LDAP group. // // GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-team func (s *AdminService) UpdateTeamLDAPMapping(ctx context.Context, team int64, mapping *TeamLDAPMapping) (*TeamLDAPMapping, *Response, error) { u := fmt.Sprintf("admin/ldap/teams/%v/mapping", team) req, err := s.client.NewRequest("PATCH", u, mapping) if err != nil { return nil, nil, err } m := new(TeamLDAPMapping) resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } go-github-28.1.1/github/admin_orgs.go000066400000000000000000000022251353501270500174250ustar00rootroot00000000000000// Copyright 2019 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import "context" // createOrgRequest is a subset of Organization and is used internally // by CreateOrg to pass only the known fields for the endpoint. type createOrgRequest struct { Login *string `json:"login,omitempty"` Admin *string `json:"admin,omitempty"` } // CreateOrg creates a new organization in GitHub Enterprise. // // Note that only a subset of the org fields are used and org must // not be nil. // // GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/orgs/#create-an-organization func (s *AdminService) CreateOrg(ctx context.Context, org *Organization, admin string) (*Organization, *Response, error) { u := "admin/organizations" orgReq := &createOrgRequest{ Login: org.Login, Admin: &admin, } req, err := s.client.NewRequest("POST", u, orgReq) if err != nil { return nil, nil, err } o := new(Organization) resp, err := s.client.Do(ctx, req, o) if err != nil { return nil, resp, err } return o, resp, nil } go-github-28.1.1/github/admin_orgs_test.go000066400000000000000000000021701353501270500204630ustar00rootroot00000000000000// Copyright 2019 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestAdminOrgs_Create(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Organization{ Login: String("github"), } mux.HandleFunc("/admin/organizations", func(w http.ResponseWriter, r *http.Request) { v := new(createOrgRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := &createOrgRequest{Login: String("github"), Admin: String("ghAdmin")} if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"login":"github","id":1}`) }) org, _, err := client.Admin.CreateOrg(context.Background(), input, "ghAdmin") if err != nil { t.Errorf("Admin.CreateOrg returned error: %v", err) } want := &Organization{ID: Int64(1), Login: String("github")} if !reflect.DeepEqual(org, want) { t.Errorf("Admin.CreateOrg returned %+v, want %+v", org, want) } } go-github-28.1.1/github/admin_stats.go000066400000000000000000000121651353501270500176150ustar00rootroot00000000000000// Copyright 2017 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" ) // AdminStats represents a variety of stats of a GitHub Enterprise // installation. type AdminStats struct { Issues *IssueStats `json:"issues,omitempty"` Hooks *HookStats `json:"hooks,omitempty"` Milestones *MilestoneStats `json:"milestones,omitempty"` Orgs *OrgStats `json:"orgs,omitempty"` Comments *CommentStats `json:"comments,omitempty"` Pages *PageStats `json:"pages,omitempty"` Users *UserStats `json:"users,omitempty"` Gists *GistStats `json:"gists,omitempty"` Pulls *PullStats `json:"pulls,omitempty"` Repos *RepoStats `json:"repos,omitempty"` } func (s AdminStats) String() string { return Stringify(s) } // IssueStats represents the number of total, open and closed issues. type IssueStats struct { TotalIssues *int `json:"total_issues,omitempty"` OpenIssues *int `json:"open_issues,omitempty"` ClosedIssues *int `json:"closed_issues,omitempty"` } func (s IssueStats) String() string { return Stringify(s) } // HookStats represents the number of total, active and inactive hooks. type HookStats struct { TotalHooks *int `json:"total_hooks,omitempty"` ActiveHooks *int `json:"active_hooks,omitempty"` InactiveHooks *int `json:"inactive_hooks,omitempty"` } func (s HookStats) String() string { return Stringify(s) } // MilestoneStats represents the number of total, open and close milestones. type MilestoneStats struct { TotalMilestones *int `json:"total_milestones,omitempty"` OpenMilestones *int `json:"open_milestones,omitempty"` ClosedMilestones *int `json:"closed_milestones,omitempty"` } func (s MilestoneStats) String() string { return Stringify(s) } // OrgStats represents the number of total, disabled organizations and the team // and team member count. type OrgStats struct { TotalOrgs *int `json:"total_orgs,omitempty"` DisabledOrgs *int `json:"disabled_orgs,omitempty"` TotalTeams *int `json:"total_teams,omitempty"` TotalTeamMembers *int `json:"total_team_members,omitempty"` } func (s OrgStats) String() string { return Stringify(s) } // CommentStats represents the number of total comments on commits, gists, issues // and pull requests. type CommentStats struct { TotalCommitComments *int `json:"total_commit_comments,omitempty"` TotalGistComments *int `json:"total_gist_comments,omitempty"` TotalIssueComments *int `json:"total_issue_comments,omitempty"` TotalPullRequestComments *int `json:"total_pull_request_comments,omitempty"` } func (s CommentStats) String() string { return Stringify(s) } // PageStats represents the total number of github pages. type PageStats struct { TotalPages *int `json:"total_pages,omitempty"` } func (s PageStats) String() string { return Stringify(s) } // UserStats represents the number of total, admin and suspended users. type UserStats struct { TotalUsers *int `json:"total_users,omitempty"` AdminUsers *int `json:"admin_users,omitempty"` SuspendedUsers *int `json:"suspended_users,omitempty"` } func (s UserStats) String() string { return Stringify(s) } // GistStats represents the number of total, private and public gists. type GistStats struct { TotalGists *int `json:"total_gists,omitempty"` PrivateGists *int `json:"private_gists,omitempty"` PublicGists *int `json:"public_gists,omitempty"` } func (s GistStats) String() string { return Stringify(s) } // PullStats represents the number of total, merged, mergable and unmergeable // pull-requests. type PullStats struct { TotalPulls *int `json:"total_pulls,omitempty"` MergedPulls *int `json:"merged_pulls,omitempty"` MergablePulls *int `json:"mergeable_pulls,omitempty"` UnmergablePulls *int `json:"unmergeable_pulls,omitempty"` } func (s PullStats) String() string { return Stringify(s) } // RepoStats represents the number of total, root, fork, organization repositories // together with the total number of pushes and wikis. type RepoStats struct { TotalRepos *int `json:"total_repos,omitempty"` RootRepos *int `json:"root_repos,omitempty"` ForkRepos *int `json:"fork_repos,omitempty"` OrgRepos *int `json:"org_repos,omitempty"` TotalPushes *int `json:"total_pushes,omitempty"` TotalWikis *int `json:"total_wikis,omitempty"` } func (s RepoStats) String() string { return Stringify(s) } // GetAdminStats returns a variety of metrics about a GitHub Enterprise // installation. // // Please note that this is only available to site administrators, // otherwise it will error with a 404 not found (instead of 401 or 403). // // GitHub API docs: https://developer.github.com/v3/enterprise-admin/admin_stats/ func (s *AdminService) GetAdminStats(ctx context.Context) (*AdminStats, *Response, error) { u := fmt.Sprintf("enterprise/stats/all") req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } m := new(AdminStats) resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } go-github-28.1.1/github/admin_stats_test.go000066400000000000000000000156561353501270500206640ustar00rootroot00000000000000package github import ( "context" "fmt" "net/http" "reflect" "testing" "time" ) func TestAdminService_GetAdminStats(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/enterprise/stats/all", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, ` { "repos": { "total_repos": 212, "root_repos": 194, "fork_repos": 18, "org_repos": 51, "total_pushes": 3082, "total_wikis": 15 }, "hooks": { "total_hooks": 27, "active_hooks": 23, "inactive_hooks": 4 }, "pages": { "total_pages": 36 }, "orgs": { "total_orgs": 33, "disabled_orgs": 0, "total_teams": 60, "total_team_members": 314 }, "users": { "total_users": 254, "admin_users": 45, "suspended_users": 21 }, "pulls": { "total_pulls": 86, "merged_pulls": 60, "mergeable_pulls": 21, "unmergeable_pulls": 3 }, "issues": { "total_issues": 179, "open_issues": 83, "closed_issues": 96 }, "milestones": { "total_milestones": 7, "open_milestones": 6, "closed_milestones": 1 }, "gists": { "total_gists": 178, "private_gists": 151, "public_gists": 25 }, "comments": { "total_commit_comments": 6, "total_gist_comments": 28, "total_issue_comments": 366, "total_pull_request_comments": 30 } } `) }) ctx := context.Background() stats, _, err := client.Admin.GetAdminStats(ctx) if err != nil { t.Errorf("AdminService.GetAdminStats returned error: %v", err) } if want := testAdminStats; !reflect.DeepEqual(stats, want) { t.Errorf("AdminService.GetAdminStats returned %+v, want %+v", stats, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Admin.GetAdminStats(ctx) if got != nil { t.Errorf("client.BaseURL.Path='' GetAdminStats = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' GetAdminStats resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' GetAdminStats err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Admin.GetAdminStats(ctx) if got != nil { t.Errorf("rate.Reset.Time > now GetAdminStats = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now GetAdminStats resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now GetAdminStats err = nil, want error") } } func TestAdminService_Stringify(t *testing.T) { want := "github.AdminStats{Issues:github.IssueStats{TotalIssues:179, OpenIssues:83, ClosedIssues:96}, Hooks:github.HookStats{TotalHooks:27, ActiveHooks:23, InactiveHooks:4}, Milestones:github.MilestoneStats{TotalMilestones:7, OpenMilestones:6, ClosedMilestones:1}, Orgs:github.OrgStats{TotalOrgs:33, DisabledOrgs:0, TotalTeams:60, TotalTeamMembers:314}, Comments:github.CommentStats{TotalCommitComments:6, TotalGistComments:28, TotalIssueComments:366, TotalPullRequestComments:30}, Pages:github.PageStats{TotalPages:36}, Users:github.UserStats{TotalUsers:254, AdminUsers:45, SuspendedUsers:21}, Gists:github.GistStats{TotalGists:178, PrivateGists:151, PublicGists:25}, Pulls:github.PullStats{TotalPulls:86, MergedPulls:60, MergablePulls:21, UnmergablePulls:3}, Repos:github.RepoStats{TotalRepos:212, RootRepos:194, ForkRepos:18, OrgRepos:51, TotalPushes:3082, TotalWikis:15}}" if got := testAdminStats.String(); got != want { t.Errorf("testAdminStats.String = %q, want %q", got, want) } want = "github.IssueStats{TotalIssues:179, OpenIssues:83, ClosedIssues:96}" if got := testAdminStats.Issues.String(); got != want { t.Errorf("testAdminStats.Issues.String = %q, want %q", got, want) } want = "github.HookStats{TotalHooks:27, ActiveHooks:23, InactiveHooks:4}" if got := testAdminStats.Hooks.String(); got != want { t.Errorf("testAdminStats.Hooks.String = %q, want %q", got, want) } want = "github.MilestoneStats{TotalMilestones:7, OpenMilestones:6, ClosedMilestones:1}" if got := testAdminStats.Milestones.String(); got != want { t.Errorf("testAdminStats.Milestones.String = %q, want %q", got, want) } want = "github.OrgStats{TotalOrgs:33, DisabledOrgs:0, TotalTeams:60, TotalTeamMembers:314}" if got := testAdminStats.Orgs.String(); got != want { t.Errorf("testAdminStats.Orgs.String = %q, want %q", got, want) } want = "github.CommentStats{TotalCommitComments:6, TotalGistComments:28, TotalIssueComments:366, TotalPullRequestComments:30}" if got := testAdminStats.Comments.String(); got != want { t.Errorf("testAdminStats.Comments.String = %q, want %q", got, want) } want = "github.PageStats{TotalPages:36}" if got := testAdminStats.Pages.String(); got != want { t.Errorf("testAdminStats.Pages.String = %q, want %q", got, want) } want = "github.UserStats{TotalUsers:254, AdminUsers:45, SuspendedUsers:21}" if got := testAdminStats.Users.String(); got != want { t.Errorf("testAdminStats.Users.String = %q, want %q", got, want) } want = "github.GistStats{TotalGists:178, PrivateGists:151, PublicGists:25}" if got := testAdminStats.Gists.String(); got != want { t.Errorf("testAdminStats.Gists.String = %q, want %q", got, want) } want = "github.PullStats{TotalPulls:86, MergedPulls:60, MergablePulls:21, UnmergablePulls:3}" if got := testAdminStats.Pulls.String(); got != want { t.Errorf("testAdminStats.Pulls.String = %q, want %q", got, want) } want = "github.RepoStats{TotalRepos:212, RootRepos:194, ForkRepos:18, OrgRepos:51, TotalPushes:3082, TotalWikis:15}" if got := testAdminStats.Repos.String(); got != want { t.Errorf("testAdminStats.Repos.String = %q, want %q", got, want) } } var testAdminStats = &AdminStats{ Repos: &RepoStats{ TotalRepos: Int(212), RootRepos: Int(194), ForkRepos: Int(18), OrgRepos: Int(51), TotalPushes: Int(3082), TotalWikis: Int(15), }, Hooks: &HookStats{ TotalHooks: Int(27), ActiveHooks: Int(23), InactiveHooks: Int(4), }, Pages: &PageStats{ TotalPages: Int(36), }, Orgs: &OrgStats{ TotalOrgs: Int(33), DisabledOrgs: Int(0), TotalTeams: Int(60), TotalTeamMembers: Int(314), }, Users: &UserStats{ TotalUsers: Int(254), AdminUsers: Int(45), SuspendedUsers: Int(21), }, Pulls: &PullStats{ TotalPulls: Int(86), MergedPulls: Int(60), MergablePulls: Int(21), UnmergablePulls: Int(3), }, Issues: &IssueStats{ TotalIssues: Int(179), OpenIssues: Int(83), ClosedIssues: Int(96), }, Milestones: &MilestoneStats{ TotalMilestones: Int(7), OpenMilestones: Int(6), ClosedMilestones: Int(1), }, Gists: &GistStats{ TotalGists: Int(178), PrivateGists: Int(151), PublicGists: Int(25), }, Comments: &CommentStats{ TotalCommitComments: Int(6), TotalGistComments: Int(28), TotalIssueComments: Int(366), TotalPullRequestComments: Int(30), }, } go-github-28.1.1/github/admin_test.go000066400000000000000000000137051353501270500174370ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" "time" ) func TestAdminService_UpdateUserLDAPMapping(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &UserLDAPMapping{ LDAPDN: String("uid=asdf,ou=users,dc=github,dc=com"), } mux.HandleFunc("/admin/ldap/users/u/mapping", func(w http.ResponseWriter, r *http.Request) { v := new(UserLDAPMapping) 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,"ldap_dn":"uid=asdf,ou=users,dc=github,dc=com"}`) }) ctx := context.Background() mapping, _, err := client.Admin.UpdateUserLDAPMapping(ctx, "u", input) if err != nil { t.Errorf("Admin.UpdateUserLDAPMapping returned error: %v", err) } want := &UserLDAPMapping{ ID: Int64(1), LDAPDN: String("uid=asdf,ou=users,dc=github,dc=com"), } if !reflect.DeepEqual(mapping, want) { t.Errorf("Admin.UpdateUserLDAPMapping returned %+v, want %+v", mapping, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Admin.UpdateUserLDAPMapping(ctx, "u", input) if got != nil { t.Errorf("client.BaseURL.Path='' UpdateUserLDAPMapping = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' UpdateUserLDAPMapping resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' UpdateUserLDAPMapping err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Admin.UpdateUserLDAPMapping(ctx, "u", input) if got != nil { t.Errorf("rate.Reset.Time > now UpdateUserLDAPMapping = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now UpdateUserLDAPMapping resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now UpdateUserLDAPMapping err = nil, want error") } } func TestAdminService_UpdateTeamLDAPMapping(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &TeamLDAPMapping{ LDAPDN: String("cn=Enterprise Ops,ou=teams,dc=github,dc=com"), } mux.HandleFunc("/admin/ldap/teams/1/mapping", func(w http.ResponseWriter, r *http.Request) { v := new(TeamLDAPMapping) 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,"ldap_dn":"cn=Enterprise Ops,ou=teams,dc=github,dc=com"}`) }) ctx := context.Background() mapping, _, err := client.Admin.UpdateTeamLDAPMapping(ctx, 1, input) if err != nil { t.Errorf("Admin.UpdateTeamLDAPMapping returned error: %v", err) } want := &TeamLDAPMapping{ ID: Int64(1), LDAPDN: String("cn=Enterprise Ops,ou=teams,dc=github,dc=com"), } if !reflect.DeepEqual(mapping, want) { t.Errorf("Admin.UpdateTeamLDAPMapping returned %+v, want %+v", mapping, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Admin.UpdateTeamLDAPMapping(ctx, 1, input) if got != nil { t.Errorf("client.BaseURL.Path='' UpdateTeamLDAPMapping = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' UpdateTeamLDAPMapping resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' UpdateTeamLDAPMapping err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Admin.UpdateTeamLDAPMapping(ctx, 1, input) if got != nil { t.Errorf("rate.Reset.Time > now UpdateTeamLDAPMapping = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now UpdateTeamLDAPMapping resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now UpdateTeamLDAPMapping err = nil, want error") } } func TestAdminService_TeamLDAPMapping_String(t *testing.T) { v := &TeamLDAPMapping{ ID: Int64(1), LDAPDN: String("a"), URL: String("b"), Name: String("c"), Slug: String("d"), Description: String("e"), Privacy: String("f"), Permission: String("g"), MembersURL: String("h"), RepositoriesURL: String("i"), } want := `github.TeamLDAPMapping{ID:1, LDAPDN:"a", URL:"b", Name:"c", Slug:"d", Description:"e", Privacy:"f", Permission:"g", MembersURL:"h", RepositoriesURL:"i"}` if got := v.String(); got != want { t.Errorf("TeamLDAPMapping.String = `%v`, want `%v`", got, want) } } func TestAdminService_UserLDAPMapping_String(t *testing.T) { v := &UserLDAPMapping{ ID: Int64(1), LDAPDN: String("a"), Login: String("b"), AvatarURL: String("c"), GravatarID: String("d"), Type: String("e"), SiteAdmin: Bool(true), URL: String("f"), EventsURL: String("g"), FollowingURL: String("h"), FollowersURL: String("i"), GistsURL: String("j"), OrganizationsURL: String("k"), ReceivedEventsURL: String("l"), ReposURL: String("m"), StarredURL: String("n"), SubscriptionsURL: String("o"), } want := `github.UserLDAPMapping{ID:1, LDAPDN:"a", Login:"b", AvatarURL:"c", GravatarID:"d", Type:"e", SiteAdmin:true, URL:"f", EventsURL:"g", FollowingURL:"h", FollowersURL:"i", GistsURL:"j", OrganizationsURL:"k", ReceivedEventsURL:"l", ReposURL:"m", StarredURL:"n", SubscriptionsURL:"o"}` if got := v.String(); got != want { t.Errorf("UserLDAPMapping.String = `%v`, want `%v`", got, want) } } go-github-28.1.1/github/admin_users.go000066400000000000000000000027751353501270500176260ustar00rootroot00000000000000// Copyright 2019 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" ) // createUserRequest is a subset of User and is used internally // by CreateUser to pass only the known fields for the endpoint. type createUserRequest struct { Login *string `json:"login,omitempty"` Email *string `json:"email,omitempty"` } // CreateUser creates a new user in GitHub Enterprise. // // GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-a-new-user func (s *AdminService) CreateUser(ctx context.Context, login, email string) (*User, *Response, error) { u := "admin/users" userReq := &createUserRequest{ Login: &login, Email: &email, } req, err := s.client.NewRequest("POST", u, userReq) if err != nil { return nil, nil, err } var user User resp, err := s.client.Do(ctx, req, &user) if err != nil { return nil, resp, err } return &user, resp, nil } // DeleteUser deletes a user in GitHub Enterprise. // // GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-a-user func (s *AdminService) DeleteUser(ctx context.Context, username string) (*Response, error) { u := "admin/users/" + username req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } resp, err := s.client.Do(ctx, req, nil) if err != nil { return resp, err } return resp, nil } go-github-28.1.1/github/admin_users_test.go000066400000000000000000000026671353501270500206650ustar00rootroot00000000000000// Copyright 2019 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestAdminUsers_Create(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/admin/users", func(w http.ResponseWriter, r *http.Request) { v := new(createUserRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := &createUserRequest{Login: String("github"), Email: String("email@domain.com")} if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"login":"github","id":1}`) }) org, _, err := client.Admin.CreateUser(context.Background(), "github", "email@domain.com") if err != nil { t.Errorf("Admin.CreateUser returned error: %v", err) } want := &User{ID: Int64(1), Login: String("github")} if !reflect.DeepEqual(org, want) { t.Errorf("Admin.CreateUser returned %+v, want %+v", org, want) } } func TestAdminUsers_Delete(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/admin/users/github", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Admin.DeleteUser(context.Background(), "github") if err != nil { t.Errorf("Admin.DeleteUser returned error: %v", err) } } go-github-28.1.1/github/apps.go000066400000000000000000000263321353501270500162530ustar00rootroot00000000000000// Copyright 2016 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "time" ) // AppsService provides access to the installation related functions // in the GitHub API. // // GitHub API docs: https://developer.github.com/v3/apps/ type AppsService service // App represents a GitHub App. type App struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` Owner *User `json:"owner,omitempty"` Name *string `json:"name,omitempty"` Description *string `json:"description,omitempty"` ExternalURL *string `json:"external_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` } // InstallationToken represents an installation token. type InstallationToken struct { Token *string `json:"token,omitempty"` ExpiresAt *time.Time `json:"expires_at,omitempty"` Permissions *InstallationPermissions `json:"permissions,omitempty"` Repositories []*Repository `json:"repositories,omitempty"` } // InstallationTokenOptions allow restricting a token's access to specific repositories. type InstallationTokenOptions struct { // The IDs of the repositories that the installation token can access. // Providing repository IDs restricts the access of an installation token to specific repositories. RepositoryIDs []int64 `json:"repository_ids,omitempty"` // The permissions granted to the access token. // The permissions object includes the permission names and their access type. Permissions *InstallationPermissions `json:"permissions,omitempty"` } // InstallationPermissions lists the repository and organization permissions for an installation. // // Permission names taken from: // https://developer.github.com/v3/apps/permissions/ // https://developer.github.com/enterprise/v3/apps/permissions/ type InstallationPermissions struct { Administration *string `json:"administration,omitempty"` Checks *string `json:"checks,omitempty"` Contents *string `json:"contents,omitempty"` ContentReferences *string `json:"content_references,omitempty"` Deployments *string `json:"deployments,omitempty"` Issues *string `json:"issues,omitempty"` Metadata *string `json:"metadata,omitempty"` Members *string `json:"members,omitempty"` OrganizationAdministration *string `json:"organization_administration,omitempty"` OrganizationHooks *string `json:"organization_hooks,omitempty"` OrganizationPlan *string `json:"organization_plan,omitempty"` OrganizationPreReceiveHooks *string `json:"organization_pre_receive_hooks,omitempty"` OrganizationProjects *string `json:"organization_projects,omitempty"` OrganizationUserBlocking *string `json:"organization_user_blocking,omitempty"` Packages *string `json:"packages,omitempty"` Pages *string `json:"pages,omitempty"` PullRequests *string `json:"pull_requests,omitempty"` RepositoryHooks *string `json:"repository_hooks,omitempty"` RepositoryProjects *string `json:"repository_projects,omitempty"` RepositoryPreReceiveHooks *string `json:"repository_pre_receive_hooks,omitempty"` SingleFile *string `json:"single_file,omitempty"` Statuses *string `json:"statuses,omitempty"` TeamDiscussions *string `json:"team_discussions,omitempty"` VulnerabilityAlerts *string `json:"vulnerability_alerts,omitempty"` } // Installation represents a GitHub Apps installation. type Installation struct { ID *int64 `json:"id,omitempty"` AppID *int64 `json:"app_id,omitempty"` TargetID *int64 `json:"target_id,omitempty"` Account *User `json:"account,omitempty"` AccessTokensURL *string `json:"access_tokens_url,omitempty"` RepositoriesURL *string `json:"repositories_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` TargetType *string `json:"target_type,omitempty"` SingleFileName *string `json:"single_file_name,omitempty"` RepositorySelection *string `json:"repository_selection,omitempty"` Events []string `json:"events,omitempty"` Permissions *InstallationPermissions `json:"permissions,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` } // Attachment represents a GitHub Apps attachment. type Attachment struct { ID *int64 `json:"id,omitempty"` Title *string `json:"title,omitempty"` Body *string `json:"body,omitempty"` } func (i Installation) String() string { return Stringify(i) } // Get a single GitHub App. Passing the empty string will get // the authenticated GitHub App. // // Note: appSlug is just the URL-friendly name of your GitHub App. // You can find this on the settings page for your GitHub App // (e.g., https://github.com/settings/apps/:app_slug). // // GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-github-app func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) { var u string if appSlug != "" { u = fmt.Sprintf("apps/%v", appSlug) } else { u = "app" } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeIntegrationPreview) app := new(App) resp, err := s.client.Do(ctx, req, app) if err != nil { return nil, resp, err } return app, resp, nil } // ListInstallations lists the installations that the current GitHub App has. // // GitHub API docs: https://developer.github.com/v3/apps/#find-installations func (s *AppsService) ListInstallations(ctx context.Context, opt *ListOptions) ([]*Installation, *Response, error) { u, err := addOptions("app/installations", opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeIntegrationPreview) var i []*Installation resp, err := s.client.Do(ctx, req, &i) if err != nil { return nil, resp, err } return i, resp, nil } // GetInstallation returns the specified installation. // // GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-installation func (s *AppsService) GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) { return s.getInstallation(ctx, fmt.Sprintf("app/installations/%v", id)) } // ListUserInstallations lists installations that are accessible to the authenticated user. // // GitHub API docs: https://developer.github.com/v3/apps/#list-installations-for-user func (s *AppsService) ListUserInstallations(ctx context.Context, opt *ListOptions) ([]*Installation, *Response, error) { u, err := addOptions("user/installations", opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeIntegrationPreview) var i struct { Installations []*Installation `json:"installations"` } resp, err := s.client.Do(ctx, req, &i) if err != nil { return nil, resp, err } return i.Installations, resp, nil } // CreateInstallationToken creates a new installation token. // // GitHub API docs: https://developer.github.com/v3/apps/#create-a-new-installation-token func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64, opt *InstallationTokenOptions) (*InstallationToken, *Response, error) { u := fmt.Sprintf("app/installations/%v/access_tokens", id) req, err := s.client.NewRequest("POST", u, opt) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeIntegrationPreview) t := new(InstallationToken) resp, err := s.client.Do(ctx, req, t) if err != nil { return nil, resp, err } return t, resp, nil } // Create a new attachment on user comment containing a url. // // GitHub API docs: https://developer.github.com/v3/apps/#create-a-content-attachment func (s *AppsService) CreateAttachment(ctx context.Context, contentReferenceID int64, title, body string) (*Attachment, *Response, error) { u := fmt.Sprintf("content_references/%v/attachments", contentReferenceID) payload := &Attachment{Title: String(title), Body: String(body)} req, err := s.client.NewRequest("POST", u, payload) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. req.Header.Set("Accept", mediaTypeReactionsPreview) m := &Attachment{} resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } // FindOrganizationInstallation finds the organization's installation information. // // GitHub API docs: https://developer.github.com/v3/apps/#find-organization-installation func (s *AppsService) FindOrganizationInstallation(ctx context.Context, org string) (*Installation, *Response, error) { return s.getInstallation(ctx, fmt.Sprintf("orgs/%v/installation", org)) } // FindRepositoryInstallation finds the repository's installation information. // // GitHub API docs: https://developer.github.com/v3/apps/#find-repository-installation func (s *AppsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*Installation, *Response, error) { return s.getInstallation(ctx, fmt.Sprintf("repos/%v/%v/installation", owner, repo)) } // FindRepositoryInstallationByID finds the repository's installation information. // // Note: FindRepositoryInstallationByID uses the undocumented GitHub API endpoint /repositories/:id/installation. func (s *AppsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*Installation, *Response, error) { return s.getInstallation(ctx, fmt.Sprintf("repositories/%d/installation", id)) } // FindUserInstallation finds the user's installation information. // // GitHub API docs: https://developer.github.com/v3/apps/#find-repository-installation func (s *AppsService) FindUserInstallation(ctx context.Context, user string) (*Installation, *Response, error) { return s.getInstallation(ctx, fmt.Sprintf("users/%v/installation", user)) } func (s *AppsService) getInstallation(ctx context.Context, url string) (*Installation, *Response, error) { req, err := s.client.NewRequest("GET", url, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeIntegrationPreview) i := new(Installation) resp, err := s.client.Do(ctx, req, i) if err != nil { return nil, resp, err } return i, resp, nil } go-github-28.1.1/github/apps_installation.go000066400000000000000000000060221353501270500210260ustar00rootroot00000000000000// 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" ) // ListRepos lists the repositories that are accessible to the authenticated installation. // // GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories func (s *AppsService) ListRepos(ctx context.Context, opt *ListOptions) ([]*Repository, *Response, error) { u, err := addOptions("installation/repositories", opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeIntegrationPreview) var r struct { Repositories []*Repository `json:"repositories"` } resp, err := s.client.Do(ctx, req, &r) if err != nil { return nil, resp, err } return r.Repositories, resp, nil } // ListUserRepos lists repositories that are accessible // to the authenticated user for an installation. // // GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories-accessible-to-the-user-for-an-installation func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opt *ListOptions) ([]*Repository, *Response, error) { u := fmt.Sprintf("user/installations/%v/repositories", id) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeIntegrationPreview) var r struct { Repositories []*Repository `json:"repositories"` } resp, err := s.client.Do(ctx, req, &r) if err != nil { return nil, resp, err } return r.Repositories, resp, nil } // AddRepository adds a single repository to an installation. // // GitHub API docs: https://developer.github.com/v3/apps/installations/#add-repository-to-installation func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (*Repository, *Response, error) { u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeIntegrationPreview) r := new(Repository) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // RemoveRepository removes a single repository from an installation. // // GitHub 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) if err != nil { return nil, err } req.Header.Set("Accept", mediaTypeIntegrationPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/apps_installation_test.go000066400000000000000000000060361353501270500220720ustar00rootroot00000000000000// 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" "reflect" "testing" ) func TestAppsService_ListRepos(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/installation/repositories", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) testFormValues(t, r, values{ "page": "1", "per_page": "2", }) fmt.Fprint(w, `{"repositories": [{"id":1}]}`) }) opt := &ListOptions{Page: 1, PerPage: 2} repositories, _, err := client.Apps.ListRepos(context.Background(), opt) if err != nil { t.Errorf("Apps.ListRepos returned error: %v", err) } want := []*Repository{{ID: Int64(1)}} if !reflect.DeepEqual(repositories, want) { t.Errorf("Apps.ListRepos returned %+v, want %+v", repositories, want) } } func TestAppsService_ListUserRepos(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/installations/1/repositories", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) testFormValues(t, r, values{ "page": "1", "per_page": "2", }) fmt.Fprint(w, `{"repositories": [{"id":1}]}`) }) opt := &ListOptions{Page: 1, PerPage: 2} repositories, _, err := client.Apps.ListUserRepos(context.Background(), 1, opt) if err != nil { t.Errorf("Apps.ListUserRepos returned error: %v", err) } want := []*Repository{{ID: Int64(1)}} if !reflect.DeepEqual(repositories, want) { t.Errorf("Apps.ListUserRepos returned %+v, want %+v", repositories, want) } } func TestAppsService_AddRepository(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/installations/1/repositories/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`) }) repo, _, err := client.Apps.AddRepository(context.Background(), 1, 1) if err != nil { t.Errorf("Apps.AddRepository returned error: %v", err) } want := &Repository{ID: Int64(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}, License: &License{Key: String("mit")}} if !reflect.DeepEqual(repo, want) { t.Errorf("AddRepository returned %+v, want %+v", repo, want) } } func TestAppsService_RemoveRepository(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/installations/1/repositories/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Apps.RemoveRepository(context.Background(), 1, 1) if err != nil { t.Errorf("Apps.RemoveRepository returned error: %v", err) } } go-github-28.1.1/github/apps_marketplace.go000066400000000000000000000153161353501270500206230ustar00rootroot00000000000000// Copyright 2017 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" ) // MarketplaceService handles communication with the marketplace related // methods of the GitHub API. // // GitHub API docs: https://developer.github.com/v3/apps/marketplace/ type MarketplaceService struct { client *Client // Stubbed controls whether endpoints that return stubbed data are used // instead of production endpoints. Stubbed data is fake data that's useful // for testing your GitHub Apps. Stubbed data is hard-coded and will not // change based on actual subscriptions. // // GitHub API docs: https://developer.github.com/v3/apps/marketplace/ Stubbed bool } // MarketplacePlan represents a GitHub Apps Marketplace Listing Plan. type MarketplacePlan struct { URL *string `json:"url,omitempty"` AccountsURL *string `json:"accounts_url,omitempty"` ID *int64 `json:"id,omitempty"` Name *string `json:"name,omitempty"` Description *string `json:"description,omitempty"` MonthlyPriceInCents *int `json:"monthly_price_in_cents,omitempty"` YearlyPriceInCents *int `json:"yearly_price_in_cents,omitempty"` // The pricing model for this listing. Can be one of "flat-rate", "per-unit", or "free". PriceModel *string `json:"price_model,omitempty"` UnitName *string `json:"unit_name,omitempty"` Bullets *[]string `json:"bullets,omitempty"` // State can be one of the values "draft" or "published". State *string `json:"state,omitempty"` HasFreeTrial *bool `json:"has_free_trial,omitempty"` } // MarketplacePurchase represents a GitHub Apps Marketplace Purchase. type MarketplacePurchase struct { // BillingCycle can be one of the values "yearly", "monthly" or nil. BillingCycle *string `json:"billing_cycle,omitempty"` NextBillingDate *Timestamp `json:"next_billing_date,omitempty"` UnitCount *int `json:"unit_count,omitempty"` Plan *MarketplacePlan `json:"plan,omitempty"` Account *MarketplacePlanAccount `json:"account,omitempty"` OnFreeTrial *bool `json:"on_free_trial,omitempty"` FreeTrialEndsOn *Timestamp `json:"free_trial_ends_on,omitempty"` } // MarketplacePendingChange represents a pending change to a GitHub Apps Marketplace Plan. type MarketplacePendingChange struct { EffectiveDate *Timestamp `json:"effective_date,omitempty"` UnitCount *int `json:"unit_count,omitempty"` ID *int64 `json:"id,omitempty"` Plan *MarketplacePlan `json:"plan,omitempty"` } // MarketplacePlanAccount represents a GitHub Account (user or organization) on a specific plan. type MarketplacePlanAccount struct { URL *string `json:"url,omitempty"` Type *string `json:"type,omitempty"` ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` Login *string `json:"login,omitempty"` Email *string `json:"email,omitempty"` OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"` MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` MarketplacePendingChange *MarketplacePendingChange `json:"marketplace_pending_change,omitempty"` } // ListPlans lists all plans for your Marketplace listing. // // GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-plans-for-your-marketplace-listing func (s *MarketplaceService) ListPlans(ctx context.Context, opt *ListOptions) ([]*MarketplacePlan, *Response, error) { uri := s.marketplaceURI("plans") u, err := addOptions(uri, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var plans []*MarketplacePlan resp, err := s.client.Do(ctx, req, &plans) if err != nil { return nil, resp, err } return plans, resp, nil } // ListPlanAccountsForPlan lists all GitHub accounts (user or organization) on a specific plan. // // GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-github-accounts-user-or-organization-on-a-specific-plan func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID int64, opt *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { uri := s.marketplaceURI(fmt.Sprintf("plans/%v/accounts", planID)) u, err := addOptions(uri, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var accounts []*MarketplacePlanAccount resp, err := s.client.Do(ctx, req, &accounts) if err != nil { return nil, resp, err } return accounts, resp, nil } // ListPlanAccountsForAccount lists all GitHub accounts (user or organization) associated with an account. // // GitHub API docs: https://developer.github.com/v3/apps/marketplace/#check-if-a-github-account-is-associated-with-any-marketplace-listing func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, accountID int64, opt *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { uri := s.marketplaceURI(fmt.Sprintf("accounts/%v", accountID)) u, err := addOptions(uri, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var accounts []*MarketplacePlanAccount resp, err := s.client.Do(ctx, req, &accounts) if err != nil { return nil, resp, err } return accounts, resp, nil } // 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 func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opt *ListOptions) ([]*MarketplacePurchase, *Response, error) { uri := "user/marketplace_purchases" if s.Stubbed { uri = "user/marketplace_purchases/stubbed" } u, err := addOptions(uri, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var purchases []*MarketplacePurchase resp, err := s.client.Do(ctx, req, &purchases) if err != nil { return nil, resp, err } return purchases, resp, nil } func (s *MarketplaceService) marketplaceURI(endpoint string) string { url := "marketplace_listing" if s.Stubbed { url = "marketplace_listing/stubbed" } return url + "/" + endpoint } go-github-28.1.1/github/apps_marketplace_test.go000066400000000000000000000144651353501270500216660ustar00rootroot00000000000000// Copyright 2017 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" "reflect" "testing" ) func TestMarketplaceService_ListPlans(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/marketplace_listing/plans", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "1", "per_page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} client.Marketplace.Stubbed = false plans, _, err := client.Marketplace.ListPlans(context.Background(), opt) if err != nil { t.Errorf("Marketplace.ListPlans returned error: %v", err) } want := []*MarketplacePlan{{ID: Int64(1)}} if !reflect.DeepEqual(plans, want) { t.Errorf("Marketplace.ListPlans returned %+v, want %+v", plans, want) } } func TestMarketplaceService_Stubbed_ListPlans(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/marketplace_listing/stubbed/plans", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} client.Marketplace.Stubbed = true plans, _, err := client.Marketplace.ListPlans(context.Background(), opt) if err != nil { t.Errorf("Marketplace.ListPlans (Stubbed) returned error: %v", err) } want := []*MarketplacePlan{{ID: Int64(1)}} if !reflect.DeepEqual(plans, want) { t.Errorf("Marketplace.ListPlans (Stubbed) returned %+v, want %+v", plans, want) } } func TestMarketplaceService_ListPlanAccountsForPlan(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/marketplace_listing/plans/1/accounts", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} client.Marketplace.Stubbed = false accounts, _, err := client.Marketplace.ListPlanAccountsForPlan(context.Background(), 1, opt) if err != nil { t.Errorf("Marketplace.ListPlanAccountsForPlan returned error: %v", err) } want := []*MarketplacePlanAccount{{ID: Int64(1)}} if !reflect.DeepEqual(accounts, want) { t.Errorf("Marketplace.ListPlanAccountsForPlan returned %+v, want %+v", accounts, want) } } func TestMarketplaceService_Stubbed_ListPlanAccountsForPlan(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/marketplace_listing/stubbed/plans/1/accounts", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} client.Marketplace.Stubbed = true accounts, _, err := client.Marketplace.ListPlanAccountsForPlan(context.Background(), 1, opt) if err != nil { t.Errorf("Marketplace.ListPlanAccountsForPlan (Stubbed) returned error: %v", err) } want := []*MarketplacePlanAccount{{ID: Int64(1)}} if !reflect.DeepEqual(accounts, want) { t.Errorf("Marketplace.ListPlanAccountsForPlan (Stubbed) returned %+v, want %+v", accounts, want) } } func TestMarketplaceService_ListPlanAccountsForAccount(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/marketplace_listing/accounts/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1, "marketplace_pending_change": {"id": 77}}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} client.Marketplace.Stubbed = false accounts, _, err := client.Marketplace.ListPlanAccountsForAccount(context.Background(), 1, opt) if err != nil { t.Errorf("Marketplace.ListPlanAccountsForAccount returned error: %v", err) } want := []*MarketplacePlanAccount{{ID: Int64(1), MarketplacePendingChange: &MarketplacePendingChange{ID: Int64(77)}}} if !reflect.DeepEqual(accounts, want) { t.Errorf("Marketplace.ListPlanAccountsForAccount returned %+v, want %+v", accounts, want) } } func TestMarketplaceService_Stubbed_ListPlanAccountsForAccount(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/marketplace_listing/stubbed/accounts/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} client.Marketplace.Stubbed = true accounts, _, err := client.Marketplace.ListPlanAccountsForAccount(context.Background(), 1, opt) if err != nil { t.Errorf("Marketplace.ListPlanAccountsForAccount (Stubbed) returned error: %v", err) } want := []*MarketplacePlanAccount{{ID: Int64(1)}} if !reflect.DeepEqual(accounts, want) { t.Errorf("Marketplace.ListPlanAccountsForAccount (Stubbed) returned %+v, want %+v", accounts, want) } } func TestMarketplaceService_ListMarketplacePurchasesForUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/marketplace_purchases", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"billing_cycle":"monthly"}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} client.Marketplace.Stubbed = false purchases, _, err := client.Marketplace.ListMarketplacePurchasesForUser(context.Background(), opt) if err != nil { t.Errorf("Marketplace.ListMarketplacePurchasesForUser returned error: %v", err) } want := []*MarketplacePurchase{{BillingCycle: String("monthly")}} if !reflect.DeepEqual(purchases, want) { t.Errorf("Marketplace.ListMarketplacePurchasesForUser returned %+v, want %+v", purchases, want) } } func TestMarketplaceService_Stubbed_ListMarketplacePurchasesForUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/marketplace_purchases/stubbed", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"billing_cycle":"monthly"}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} client.Marketplace.Stubbed = true purchases, _, err := client.Marketplace.ListMarketplacePurchasesForUser(context.Background(), opt) if err != nil { t.Errorf("Marketplace.ListMarketplacePurchasesForUser returned error: %v", err) } want := []*MarketplacePurchase{{BillingCycle: String("monthly")}} if !reflect.DeepEqual(purchases, want) { t.Errorf("Marketplace.ListMarketplacePurchasesForUser returned %+v, want %+v", purchases, want) } } go-github-28.1.1/github/apps_test.go000066400000000000000000000345761353501270500173230ustar00rootroot00000000000000// 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 ( "bytes" "context" "encoding/json" "fmt" "io" "io/ioutil" "net/http" "reflect" "testing" "time" ) func TestAppsService_Get_authenticatedApp(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/app", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) fmt.Fprint(w, `{"id":1}`) }) app, _, err := client.Apps.Get(context.Background(), "") if err != nil { t.Errorf("Apps.Get returned error: %v", err) } want := &App{ID: Int64(1)} if !reflect.DeepEqual(app, want) { t.Errorf("Apps.Get returned %+v, want %+v", app, want) } } func TestAppsService_Get_specifiedApp(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/apps/a", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) fmt.Fprint(w, `{"html_url":"https://github.com/apps/a"}`) }) app, _, err := client.Apps.Get(context.Background(), "a") if err != nil { t.Errorf("Apps.Get returned error: %v", err) } want := &App{HTMLURL: String("https://github.com/apps/a")} if !reflect.DeepEqual(app, want) { t.Errorf("Apps.Get returned %+v, want %+v", *app.HTMLURL, *want.HTMLURL) } } func TestAppsService_ListInstallations(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/app/installations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) testFormValues(t, r, values{ "page": "1", "per_page": "2", }) fmt.Fprint(w, `[{ "id":1, "app_id":1, "target_id":1, "target_type": "Organization", "permissions": { "administration": "read", "checks": "read", "contents": "read", "content_references": "read", "deployments": "read", "issues": "write", "metadata": "read", "members": "read", "organization_administration": "write", "organization_hooks": "write", "organization_plan": "read", "organization_pre_receive_hooks": "write", "organization_projects": "read", "organization_user_blocking": "write", "packages": "read", "pages": "read", "pull_requests": "write", "repository_hooks": "write", "repository_projects": "read", "repository_pre_receive_hooks": "read", "single_file": "write", "statuses": "write", "team_discussions": "read", "vulnerability_alerts": "read" }, "events": [ "push", "pull_request" ], "single_file_name": "config.yml", "repository_selection": "selected", "created_at": "2018-01-01T00:00:00Z", "updated_at": "2018-01-01T00:00:00Z"}]`, ) }) opt := &ListOptions{Page: 1, PerPage: 2} installations, _, err := client.Apps.ListInstallations(context.Background(), opt) if err != nil { t.Errorf("Apps.ListInstallations returned error: %v", err) } date := Timestamp{Time: time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)} want := []*Installation{{ ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization"), SingleFileName: String("config.yml"), RepositorySelection: String("selected"), Permissions: &InstallationPermissions{ Administration: String("read"), Checks: String("read"), Contents: String("read"), ContentReferences: String("read"), Deployments: String("read"), Issues: String("write"), Metadata: String("read"), Members: String("read"), OrganizationAdministration: String("write"), OrganizationHooks: String("write"), OrganizationPlan: String("read"), OrganizationPreReceiveHooks: String("write"), OrganizationProjects: String("read"), OrganizationUserBlocking: String("write"), Packages: String("read"), Pages: String("read"), PullRequests: String("write"), RepositoryHooks: String("write"), RepositoryProjects: String("read"), RepositoryPreReceiveHooks: String("read"), SingleFile: String("write"), Statuses: String("write"), TeamDiscussions: String("read"), VulnerabilityAlerts: String("read")}, Events: []string{"push", "pull_request"}, CreatedAt: &date, UpdatedAt: &date, }} if !reflect.DeepEqual(installations, want) { t.Errorf("Apps.ListInstallations returned %+v, want %+v", installations, want) } } func TestAppsService_GetInstallation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/app/installations/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`) }) installation, _, err := client.Apps.GetInstallation(context.Background(), 1) if err != nil { t.Errorf("Apps.GetInstallation returned error: %v", err) } want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")} if !reflect.DeepEqual(installation, want) { t.Errorf("Apps.GetInstallation returned %+v, want %+v", installation, want) } } func TestAppsService_ListUserInstallations(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/installations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) testFormValues(t, r, values{ "page": "1", "per_page": "2", }) fmt.Fprint(w, `{"installations":[{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}]}`) }) opt := &ListOptions{Page: 1, PerPage: 2} installations, _, err := client.Apps.ListUserInstallations(context.Background(), opt) if err != nil { t.Errorf("Apps.ListUserInstallations returned error: %v", err) } want := []*Installation{{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}} if !reflect.DeepEqual(installations, want) { t.Errorf("Apps.ListUserInstallations returned %+v, want %+v", installations, want) } } func TestAppsService_CreateInstallationToken(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/app/installations/1/access_tokens", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) fmt.Fprint(w, `{"token":"t"}`) }) token, _, err := client.Apps.CreateInstallationToken(context.Background(), 1, nil) if err != nil { t.Errorf("Apps.CreateInstallationToken returned error: %v", err) } want := &InstallationToken{Token: String("t")} if !reflect.DeepEqual(token, want) { t.Errorf("Apps.CreateInstallationToken returned %+v, want %+v", token, want) } } func TestAppsService_CreateInstallationTokenWithOptions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() installationTokenOptions := &InstallationTokenOptions{ RepositoryIDs: []int64{1234}, Permissions: &InstallationPermissions{ Contents: String("write"), Issues: String("read"), }, } // Convert InstallationTokenOptions into an io.ReadCloser object for comparison. wantBody, err := GetReadCloser(installationTokenOptions) if err != nil { t.Errorf("GetReadCloser returned error: %v", err) } mux.HandleFunc("/app/installations/1/access_tokens", func(w http.ResponseWriter, r *http.Request) { // Read request body contents. var gotBodyBytes []byte gotBodyBytes, err = ioutil.ReadAll(r.Body) if err != nil { t.Errorf("ReadAll returned error: %v", err) } r.Body = ioutil.NopCloser(bytes.NewBuffer(gotBodyBytes)) if !reflect.DeepEqual(r.Body, wantBody) { t.Errorf("request sent %+v, want %+v", r.Body, wantBody) } testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) fmt.Fprint(w, `{"token":"t"}`) }) token, _, err := client.Apps.CreateInstallationToken(context.Background(), 1, installationTokenOptions) if err != nil { t.Errorf("Apps.CreateInstallationToken returned error: %v", err) } want := &InstallationToken{Token: String("t")} if !reflect.DeepEqual(token, want) { t.Errorf("Apps.CreateInstallationToken returned %+v, want %+v", token, want) } } func TestAppsService_CreateAttachement(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/content_references/11/attachments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusOK) w.Write([]byte(`{"id":1,"title":"title1","body":"body1"}`)) }) got, _, err := client.Apps.CreateAttachment(context.Background(), 11, "title1", "body1") if err != nil { t.Errorf("CreateAttachment returned error: %v", err) } want := &Attachment{ID: Int64(1), Title: String("title1"), Body: String("body1")} if !reflect.DeepEqual(got, want) { t.Errorf("CreateAttachment = %+v, want %+v", got, want) } } func TestAppsService_FindOrganizationInstallation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/installation", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`) }) installation, _, err := client.Apps.FindOrganizationInstallation(context.Background(), "o") if err != nil { t.Errorf("Apps.FindOrganizationInstallation returned error: %v", err) } want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")} if !reflect.DeepEqual(installation, want) { t.Errorf("Apps.FindOrganizationInstallation returned %+v, want %+v", installation, want) } } func TestAppsService_FindRepositoryInstallation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/installation", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`) }) installation, _, err := client.Apps.FindRepositoryInstallation(context.Background(), "o", "r") if err != nil { t.Errorf("Apps.FindRepositoryInstallation returned error: %v", err) } want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")} if !reflect.DeepEqual(installation, want) { t.Errorf("Apps.FindRepositoryInstallation returned %+v, want %+v", installation, want) } } func TestAppsService_FindRepositoryInstallationByID(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repositories/1/installation", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`) }) installation, _, err := client.Apps.FindRepositoryInstallationByID(context.Background(), 1) if err != nil { t.Errorf("Apps.FindRepositoryInstallationByID returned error: %v", err) } want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")} if !reflect.DeepEqual(installation, want) { t.Errorf("Apps.FindRepositoryInstallationByID returned %+v, want %+v", installation, want) } } func TestAppsService_FindUserInstallation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/installation", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeIntegrationPreview) fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "User"}`) }) installation, _, err := client.Apps.FindUserInstallation(context.Background(), "u") if err != nil { t.Errorf("Apps.FindUserInstallation returned error: %v", err) } want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("User")} if !reflect.DeepEqual(installation, want) { t.Errorf("Apps.FindUserInstallation returned %+v, want %+v", installation, want) } } // GetReadWriter converts a body interface into an io.ReadWriter object. func GetReadWriter(body interface{}) (io.ReadWriter, error) { var buf io.ReadWriter if body != nil { buf = new(bytes.Buffer) enc := json.NewEncoder(buf) err := enc.Encode(body) if err != nil { return nil, err } } return buf, nil } // GetReadCloser converts a body interface into an io.ReadCloser object. func GetReadCloser(body interface{}) (io.ReadCloser, error) { buf, err := GetReadWriter(body) if err != nil { return nil, err } all, err := ioutil.ReadAll(buf) if err != nil { return nil, err } return ioutil.NopCloser(bytes.NewBuffer(all)), nil } go-github-28.1.1/github/authorizations.go000066400000000000000000000344701353501270500203750ustar00rootroot00000000000000// Copyright 2015 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" ) // Scope models a GitHub authorization scope. // // GitHub API docs: https://developer.github.com/v3/oauth/#scopes type Scope string // This is the set of scopes for GitHub API V3 const ( ScopeNone Scope = "(no scope)" // REVISIT: is this actually returned, or just a documentation artifact? ScopeUser Scope = "user" ScopeUserEmail Scope = "user:email" ScopeUserFollow Scope = "user:follow" ScopePublicRepo Scope = "public_repo" ScopeRepo Scope = "repo" ScopeRepoDeployment Scope = "repo_deployment" ScopeRepoStatus Scope = "repo:status" ScopeDeleteRepo Scope = "delete_repo" ScopeNotifications Scope = "notifications" ScopeGist Scope = "gist" ScopeReadRepoHook Scope = "read:repo_hook" ScopeWriteRepoHook Scope = "write:repo_hook" ScopeAdminRepoHook Scope = "admin:repo_hook" ScopeAdminOrgHook Scope = "admin:org_hook" ScopeReadOrg Scope = "read:org" ScopeWriteOrg Scope = "write:org" ScopeAdminOrg Scope = "admin:org" ScopeReadPublicKey Scope = "read:public_key" ScopeWritePublicKey Scope = "write:public_key" ScopeAdminPublicKey Scope = "admin:public_key" ScopeReadGPGKey Scope = "read:gpg_key" ScopeWriteGPGKey Scope = "write:gpg_key" ScopeAdminGPGKey Scope = "admin:gpg_key" ) // AuthorizationsService handles communication with the authorization related // methods of the GitHub API. // // This service requires HTTP Basic Authentication; it cannot be accessed using // an OAuth token. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/ type AuthorizationsService service // Authorization represents an individual GitHub authorization. type Authorization struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` Scopes []Scope `json:"scopes,omitempty"` Token *string `json:"token,omitempty"` TokenLastEight *string `json:"token_last_eight,omitempty"` HashedToken *string `json:"hashed_token,omitempty"` App *AuthorizationApp `json:"app,omitempty"` Note *string `json:"note,omitempty"` NoteURL *string `json:"note_url,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` Fingerprint *string `json:"fingerprint,omitempty"` // User is only populated by the Check and Reset methods. User *User `json:"user,omitempty"` } func (a Authorization) String() string { return Stringify(a) } // AuthorizationApp represents an individual GitHub app (in the context of authorization). type AuthorizationApp struct { URL *string `json:"url,omitempty"` Name *string `json:"name,omitempty"` ClientID *string `json:"client_id,omitempty"` } func (a AuthorizationApp) String() string { return Stringify(a) } // Grant represents an OAuth application that has been granted access to an account. type Grant struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` App *AuthorizationApp `json:"app,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` Scopes []string `json:"scopes,omitempty"` } func (g Grant) String() string { return Stringify(g) } // AuthorizationRequest represents a request to create an authorization. type AuthorizationRequest struct { Scopes []Scope `json:"scopes,omitempty"` Note *string `json:"note,omitempty"` NoteURL *string `json:"note_url,omitempty"` ClientID *string `json:"client_id,omitempty"` ClientSecret *string `json:"client_secret,omitempty"` Fingerprint *string `json:"fingerprint,omitempty"` } func (a AuthorizationRequest) String() string { return Stringify(a) } // AuthorizationUpdateRequest represents a request to update an authorization. // // Note that for any one update, you must only provide one of the "scopes" // fields. That is, you may provide only one of "Scopes", or "AddScopes", or // "RemoveScopes". // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization type AuthorizationUpdateRequest struct { Scopes []string `json:"scopes,omitempty"` AddScopes []string `json:"add_scopes,omitempty"` RemoveScopes []string `json:"remove_scopes,omitempty"` Note *string `json:"note,omitempty"` NoteURL *string `json:"note_url,omitempty"` Fingerprint *string `json:"fingerprint,omitempty"` } func (a AuthorizationUpdateRequest) String() string { return Stringify(a) } // List the authorizations for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-authorizations func (s *AuthorizationsService) List(ctx context.Context, opt *ListOptions) ([]*Authorization, *Response, error) { u := "authorizations" u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var auths []*Authorization resp, err := s.client.Do(ctx, req, &auths) if err != nil { return nil, resp, err } return auths, resp, nil } // Get a single authorization. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-authorization func (s *AuthorizationsService) Get(ctx context.Context, id int64) (*Authorization, *Response, error) { u := fmt.Sprintf("authorizations/%d", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } a := new(Authorization) resp, err := s.client.Do(ctx, req, a) if err != nil { return nil, resp, err } return a, resp, nil } // Create a new authorization for the specified OAuth application. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#create-a-new-authorization func (s *AuthorizationsService) Create(ctx context.Context, auth *AuthorizationRequest) (*Authorization, *Response, error) { u := "authorizations" req, err := s.client.NewRequest("POST", u, auth) if err != nil { return nil, nil, err } a := new(Authorization) resp, err := s.client.Do(ctx, req, a) if err != nil { return nil, resp, err } return a, resp, nil } // GetOrCreateForApp creates a new authorization for the specified OAuth // application, only if an authorization for that application doesn’t already // exist for the user. // // If a new token is created, the HTTP status code will be "201 Created", and // the returned Authorization.Token field will be populated. If an existing // token is returned, the status code will be "200 OK" and the // Authorization.Token field will be empty. // // clientID is the OAuth Client ID with which to create the token. // // GitHub API docs: // https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app // https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app-and-fingerprint func (s *AuthorizationsService) GetOrCreateForApp(ctx context.Context, clientID string, auth *AuthorizationRequest) (*Authorization, *Response, error) { var u string if auth.Fingerprint == nil || *auth.Fingerprint == "" { u = fmt.Sprintf("authorizations/clients/%v", clientID) } else { u = fmt.Sprintf("authorizations/clients/%v/%v", clientID, *auth.Fingerprint) } req, err := s.client.NewRequest("PUT", u, auth) if err != nil { return nil, nil, err } a := new(Authorization) resp, err := s.client.Do(ctx, req, a) if err != nil { return nil, resp, err } return a, resp, nil } // Edit a single authorization. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization func (s *AuthorizationsService) Edit(ctx context.Context, id int64, auth *AuthorizationUpdateRequest) (*Authorization, *Response, error) { u := fmt.Sprintf("authorizations/%d", id) req, err := s.client.NewRequest("PATCH", u, auth) if err != nil { return nil, nil, err } a := new(Authorization) resp, err := s.client.Do(ctx, req, a) if err != nil { return nil, resp, err } return a, resp, nil } // Delete a single authorization. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-an-authorization func (s *AuthorizationsService) Delete(ctx context.Context, id int64) (*Response, error) { u := fmt.Sprintf("authorizations/%d", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // Check if an OAuth token is valid for a specific app. // // Note that this operation requires the use of BasicAuth, but where the // username is the OAuth application clientID, and the password is its // clientSecret. Invalid tokens will return a 404 Not Found. // // The returned Authorization.User field will be populated. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#check-an-authorization func (s *AuthorizationsService) Check(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) { u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } a := new(Authorization) resp, err := s.client.Do(ctx, req, a) if err != nil { return nil, resp, err } return a, resp, nil } // Reset is used to reset a valid OAuth token without end user involvement. // Applications must save the "token" property in the response, because changes // take effect immediately. // // Note that this operation requires the use of BasicAuth, but where the // username is the OAuth application clientID, and the password is its // clientSecret. Invalid tokens will return a 404 Not Found. // // The returned Authorization.User field will be populated. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#reset-an-authorization func (s *AuthorizationsService) Reset(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) { u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, nil, err } a := new(Authorization) resp, err := s.client.Do(ctx, req, a) if err != nil { return nil, resp, err } return a, resp, nil } // Revoke an authorization for an application. // // Note that this operation requires the use of BasicAuth, but where the // username is the OAuth application clientID, and the password is its // clientSecret. Invalid tokens will return a 404 Not Found. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#revoke-an-authorization-for-an-application func (s *AuthorizationsService) Revoke(ctx context.Context, clientID string, token string) (*Response, error) { u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // ListGrants lists the set of OAuth applications that have been granted // access to a user's account. This will return one entry for each application // that has been granted access to the account, regardless of the number of // tokens an application has generated for the user. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-grants func (s *AuthorizationsService) ListGrants(ctx context.Context, opt *ListOptions) ([]*Grant, *Response, error) { u, err := addOptions("applications/grants", opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } grants := []*Grant{} resp, err := s.client.Do(ctx, req, &grants) if err != nil { return nil, resp, err } return grants, resp, nil } // GetGrant gets a single OAuth application grant. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-grant func (s *AuthorizationsService) GetGrant(ctx context.Context, id int64) (*Grant, *Response, error) { u := fmt.Sprintf("applications/grants/%d", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } grant := new(Grant) resp, err := s.client.Do(ctx, req, grant) if err != nil { return nil, resp, err } return grant, resp, nil } // DeleteGrant deletes an OAuth application grant. Deleting an application's // grant will also delete all OAuth tokens associated with the application for // the user. // // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-a-grant func (s *AuthorizationsService) DeleteGrant(ctx context.Context, id int64) (*Response, error) { u := fmt.Sprintf("applications/grants/%d", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // CreateImpersonation creates an impersonation OAuth token. // // This requires admin permissions. With the returned Authorization.Token // you can e.g. create or delete a user's public SSH key. NOTE: creating a // new token automatically revokes an existing one. // // GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-an-impersonation-oauth-token func (s *AuthorizationsService) CreateImpersonation(ctx context.Context, username string, authReq *AuthorizationRequest) (*Authorization, *Response, error) { u := fmt.Sprintf("admin/users/%v/authorizations", username) req, err := s.client.NewRequest("POST", u, authReq) if err != nil { return nil, nil, err } a := new(Authorization) resp, err := s.client.Do(ctx, req, a) if err != nil { return nil, resp, err } return a, resp, nil } // DeleteImpersonation deletes an impersonation OAuth token. // // NOTE: there can be only one at a time. // // GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-an-impersonation-oauth-token func (s *AuthorizationsService) DeleteImpersonation(ctx context.Context, username string) (*Response, error) { u := fmt.Sprintf("admin/users/%v/authorizations", username) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/authorizations_test.go000066400000000000000000000232211353501270500214240ustar00rootroot00000000000000// Copyright 2015 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestAuthorizationsService_List(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/authorizations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "1", "per_page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} got, _, err := client.Authorizations.List(context.Background(), opt) if err != nil { t.Errorf("Authorizations.List returned error: %v", err) } want := []*Authorization{{ID: Int64(1)}} if !reflect.DeepEqual(got, want) { t.Errorf("Authorizations.List returned %+v, want %+v", *got[0].ID, *want[0].ID) } } func TestAuthorizationsService_Get(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/authorizations/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) got, _, err := client.Authorizations.Get(context.Background(), 1) if err != nil { t.Errorf("Authorizations.Get returned error: %v", err) } want := &Authorization{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Authorizations.Get returned auth %+v, want %+v", got, want) } } func TestAuthorizationsService_Create(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &AuthorizationRequest{ Note: String("test"), } mux.HandleFunc("/authorizations", func(w http.ResponseWriter, r *http.Request) { v := new(AuthorizationRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"ID":1}`) }) got, _, err := client.Authorizations.Create(context.Background(), input) if err != nil { t.Errorf("Authorizations.Create returned error: %v", err) } want := &Authorization{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Authorization.Create returned %+v, want %+v", got, want) } } func TestAuthorizationsService_GetOrCreateForApp(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &AuthorizationRequest{ Note: String("test"), } mux.HandleFunc("/authorizations/clients/id", func(w http.ResponseWriter, r *http.Request) { v := new(AuthorizationRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"ID":1}`) }) got, _, err := client.Authorizations.GetOrCreateForApp(context.Background(), "id", input) if err != nil { t.Errorf("Authorizations.GetOrCreateForApp returned error: %v", err) } want := &Authorization{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Authorization.GetOrCreateForApp returned %+v, want %+v", got, want) } } func TestAuthorizationsService_GetOrCreateForApp_Fingerprint(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &AuthorizationRequest{ Note: String("test"), Fingerprint: String("fp"), } mux.HandleFunc("/authorizations/clients/id/fp", func(w http.ResponseWriter, r *http.Request) { v := new(AuthorizationRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"ID":1}`) }) got, _, err := client.Authorizations.GetOrCreateForApp(context.Background(), "id", input) if err != nil { t.Errorf("Authorizations.GetOrCreateForApp returned error: %v", err) } want := &Authorization{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Authorization.GetOrCreateForApp returned %+v, want %+v", got, want) } } func TestAuthorizationsService_Edit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &AuthorizationUpdateRequest{ Note: String("test"), } mux.HandleFunc("/authorizations/1", func(w http.ResponseWriter, r *http.Request) { v := new(AuthorizationUpdateRequest) 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}`) }) got, _, err := client.Authorizations.Edit(context.Background(), 1, input) if err != nil { t.Errorf("Authorizations.Edit returned error: %v", err) } want := &Authorization{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Authorization.Update returned %+v, want %+v", got, want) } } func TestAuthorizationsService_Delete(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/authorizations/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Authorizations.Delete(context.Background(), 1) if err != nil { t.Errorf("Authorizations.Delete returned error: %v", err) } } func TestAuthorizationsService_Check(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/applications/id/tokens/t", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) got, _, err := client.Authorizations.Check(context.Background(), "id", "t") if err != nil { t.Errorf("Authorizations.Check returned error: %v", err) } want := &Authorization{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Authorizations.Check returned auth %+v, want %+v", got, want) } } func TestAuthorizationsService_Reset(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/applications/id/tokens/t", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") fmt.Fprint(w, `{"ID":1}`) }) got, _, err := client.Authorizations.Reset(context.Background(), "id", "t") if err != nil { t.Errorf("Authorizations.Reset returned error: %v", err) } want := &Authorization{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Authorizations.Reset returned auth %+v, want %+v", got, want) } } func TestAuthorizationsService_Revoke(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/applications/id/tokens/t", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Authorizations.Revoke(context.Background(), "id", "t") if err != nil { t.Errorf("Authorizations.Revoke returned error: %v", err) } } func TestListGrants(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/applications/grants", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id": 1}]`) }) got, _, err := client.Authorizations.ListGrants(context.Background(), nil) if err != nil { t.Errorf("OAuthAuthorizations.ListGrants returned error: %v", err) } want := []*Grant{{ID: Int64(1)}} if !reflect.DeepEqual(got, want) { t.Errorf("OAuthAuthorizations.ListGrants = %+v, want %+v", got, want) } } func TestListGrants_withOptions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/applications/grants", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id": 1}]`) }) _, _, err := client.Authorizations.ListGrants(context.Background(), &ListOptions{Page: 2}) if err != nil { t.Errorf("OAuthAuthorizations.ListGrants returned error: %v", err) } } func TestGetGrant(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/applications/grants/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id": 1}`) }) got, _, err := client.Authorizations.GetGrant(context.Background(), 1) if err != nil { t.Errorf("OAuthAuthorizations.GetGrant returned error: %v", err) } want := &Grant{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("OAuthAuthorizations.GetGrant = %+v, want %+v", got, want) } } func TestDeleteGrant(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/applications/grants/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Authorizations.DeleteGrant(context.Background(), 1) if err != nil { t.Errorf("OAuthAuthorizations.DeleteGrant returned error: %v", err) } } func TestAuthorizationsService_CreateImpersonation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/admin/users/u/authorizations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") fmt.Fprint(w, `{"id":1}`) }) req := &AuthorizationRequest{Scopes: []Scope{ScopePublicRepo}} got, _, err := client.Authorizations.CreateImpersonation(context.Background(), "u", req) if err != nil { t.Errorf("Authorizations.CreateImpersonation returned error: %+v", err) } want := &Authorization{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Authorizations.CreateImpersonation returned %+v, want %+v", *got.ID, *want.ID) } } func TestAuthorizationsService_DeleteImpersonation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/admin/users/u/authorizations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Authorizations.DeleteImpersonation(context.Background(), "u") if err != nil { t.Errorf("Authorizations.DeleteImpersonation returned error: %+v", err) } } go-github-28.1.1/github/checks.go000066400000000000000000000442261353501270500165520ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "net/url" ) // ChecksService provides access to the Checks API in the // GitHub API. // // GitHub API docs: https://developer.github.com/v3/checks/ type ChecksService service // CheckRun represents a GitHub check run on a repository associated with a GitHub app. type CheckRun struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` HeadSHA *string `json:"head_sha,omitempty"` ExternalID *string `json:"external_id,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` DetailsURL *string `json:"details_url,omitempty"` Status *string `json:"status,omitempty"` Conclusion *string `json:"conclusion,omitempty"` StartedAt *Timestamp `json:"started_at,omitempty"` CompletedAt *Timestamp `json:"completed_at,omitempty"` Output *CheckRunOutput `json:"output,omitempty"` Name *string `json:"name,omitempty"` CheckSuite *CheckSuite `json:"check_suite,omitempty"` App *App `json:"app,omitempty"` PullRequests []*PullRequest `json:"pull_requests,omitempty"` } // CheckRunOutput represents the output of a CheckRun. type CheckRunOutput struct { Title *string `json:"title,omitempty"` Summary *string `json:"summary,omitempty"` Text *string `json:"text,omitempty"` AnnotationsCount *int `json:"annotations_count,omitempty"` AnnotationsURL *string `json:"annotations_url,omitempty"` Annotations []*CheckRunAnnotation `json:"annotations,omitempty"` Images []*CheckRunImage `json:"images,omitempty"` } // CheckRunAnnotation represents an annotation object for a CheckRun output. type CheckRunAnnotation struct { Path *string `json:"path,omitempty"` BlobHRef *string `json:"blob_href,omitempty"` StartLine *int `json:"start_line,omitempty"` EndLine *int `json:"end_line,omitempty"` StartColumn *int `json:"start_column,omitempty"` EndColumn *int `json:"end_column,omitempty"` AnnotationLevel *string `json:"annotation_level,omitempty"` Message *string `json:"message,omitempty"` Title *string `json:"title,omitempty"` RawDetails *string `json:"raw_details,omitempty"` } // CheckRunImage represents an image object for a CheckRun output. type CheckRunImage struct { Alt *string `json:"alt,omitempty"` ImageURL *string `json:"image_url,omitempty"` Caption *string `json:"caption,omitempty"` } // CheckSuite represents a suite of check runs. type CheckSuite struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` HeadBranch *string `json:"head_branch,omitempty"` HeadSHA *string `json:"head_sha,omitempty"` URL *string `json:"url,omitempty"` BeforeSHA *string `json:"before,omitempty"` AfterSHA *string `json:"after,omitempty"` Status *string `json:"status,omitempty"` Conclusion *string `json:"conclusion,omitempty"` App *App `json:"app,omitempty"` Repository *Repository `json:"repository,omitempty"` PullRequests []*PullRequest `json:"pull_requests,omitempty"` // The following fields are only populated by Webhook events. HeadCommit *Commit `json:"head_commit,omitempty"` } func (c CheckRun) String() string { return Stringify(c) } func (c CheckSuite) String() string { return Stringify(c) } // GetCheckRun gets a check-run for a repository. // // GitHub API docs: https://developer.github.com/v3/checks/runs/#get-a-single-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) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) checkRun := new(CheckRun) resp, err := s.client.Do(ctx, req, checkRun) if err != nil { return nil, resp, err } return checkRun, resp, nil } // GetCheckSuite gets a single check suite. // // GitHub API docs: https://developer.github.com/v3/checks/suites/#get-a-single-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) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) checkSuite := new(CheckSuite) resp, err := s.client.Do(ctx, req, checkSuite) if err != nil { return nil, resp, err } return checkSuite, resp, nil } // CreateCheckRunOptions sets up parameters needed to create a CheckRun. type CreateCheckRunOptions struct { Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) HeadBranch string `json:"head_branch"` // The name of the branch to perform a check against. (Required.) HeadSHA string `json:"head_sha"` // The SHA of the commit. (Required.) DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) StartedAt *Timestamp `json:"started_at,omitempty"` // The time that the check run began. (Optional.) CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.) } // CheckRunAction exposes further actions the integrator can perform, which a user may trigger. type CheckRunAction struct { Label string `json:"label"` // The text to be displayed on a button in the web UI. The maximum size is 20 characters. (Required.) Description string `json:"description"` // A short explanation of what this action would do. The maximum size is 40 characters. (Required.) Identifier string `json:"identifier"` // A reference for the action on the integrator's system. The maximum size is 20 characters. (Required.) } // CreateCheckRun creates a check run for repository. // // GitHub API docs: https://developer.github.com/v3/checks/runs/#create-a-check-run func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string, opt CreateCheckRunOptions) (*CheckRun, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-runs", owner, repo) req, err := s.client.NewRequest("POST", u, opt) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) checkRun := new(CheckRun) resp, err := s.client.Do(ctx, req, checkRun) if err != nil { return nil, resp, err } return checkRun, resp, nil } // UpdateCheckRunOptions sets up parameters needed to update a CheckRun. type UpdateCheckRunOptions struct { Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) HeadBranch *string `json:"head_branch,omitempty"` // The name of the branch to perform a check against. (Optional.) HeadSHA *string `json:"head_sha,omitempty"` // The SHA of the commit. (Optional.) DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.) } // UpdateCheckRun updates a check run for a specific commit in a repository. // // GitHub API docs: https://developer.github.com/v3/checks/runs/#update-a-check-run func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, checkRunID int64, opt UpdateCheckRunOptions) (*CheckRun, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID) req, err := s.client.NewRequest("PATCH", u, opt) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) checkRun := new(CheckRun) resp, err := s.client.Do(ctx, req, checkRun) if err != nil { return nil, resp, err } return checkRun, resp, nil } // ListCheckRunAnnotations lists the annotations for a check run. // // GitHub API docs: https://developer.github.com/v3/checks/runs/#list-annotations-for-a-check-run func (s *ChecksService) ListCheckRunAnnotations(ctx context.Context, owner, repo string, checkRunID int64, opt *ListOptions) ([]*CheckRunAnnotation, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-runs/%v/annotations", owner, repo, checkRunID) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) var checkRunAnnotations []*CheckRunAnnotation resp, err := s.client.Do(ctx, req, &checkRunAnnotations) if err != nil { return nil, resp, err } return checkRunAnnotations, resp, nil } // ListCheckRunsOptions represents parameters to list check runs. type ListCheckRunsOptions struct { CheckName *string `url:"check_name,omitempty"` // Returns check runs with the specified name. Status *string `url:"status,omitempty"` // Returns check runs with the specified status. Can be one of "queued", "in_progress", or "completed". Filter *string `url:"filter,omitempty"` // Filters check runs by their completed_at timestamp. Can be one of "latest" (returning the most recent check runs) or "all". Default: "latest" ListOptions } // ListCheckRunsResults represents the result of a check run list. type ListCheckRunsResults struct { Total *int `json:"total_count,omitempty"` CheckRuns []*CheckRun `json:"check_runs,omitempty"` } // 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 func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, ref string, opt *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/check-runs", owner, repo, url.QueryEscape(ref)) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) var checkRunResults *ListCheckRunsResults resp, err := s.client.Do(ctx, req, &checkRunResults) if err != nil { return nil, resp, err } return checkRunResults, resp, nil } // ListCheckRunsCheckSuite lists check runs for a check suite. // // GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-in-a-check-suite func (s *ChecksService) ListCheckRunsCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64, opt *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-suites/%v/check-runs", owner, repo, checkSuiteID) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) var checkRunResults *ListCheckRunsResults resp, err := s.client.Do(ctx, req, &checkRunResults) if err != nil { return nil, resp, err } return checkRunResults, resp, nil } // ListCheckSuiteOptions represents parameters to list check suites. type ListCheckSuiteOptions struct { CheckName *string `url:"check_name,omitempty"` // Filters checks suites by the name of the check run. AppID *int `url:"app_id,omitempty"` // Filters check suites by GitHub App id. ListOptions } // ListCheckSuiteResults represents the result of a check run list. type ListCheckSuiteResults struct { Total *int `json:"total_count,omitempty"` CheckSuites []*CheckSuite `json:"check_suites,omitempty"` } // 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 func (s *ChecksService) ListCheckSuitesForRef(ctx context.Context, owner, repo, ref string, opt *ListCheckSuiteOptions) (*ListCheckSuiteResults, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/check-suites", owner, repo, url.QueryEscape(ref)) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) var checkSuiteResults *ListCheckSuiteResults resp, err := s.client.Do(ctx, req, &checkSuiteResults) if err != nil { return nil, resp, err } return checkSuiteResults, resp, nil } // AutoTriggerCheck enables or disables automatic creation of CheckSuite events upon pushes to the repository. type AutoTriggerCheck struct { AppID *int64 `json:"app_id,omitempty"` // The id of the GitHub App. (Required.) Setting *bool `json:"setting,omitempty"` // Set to "true" to enable automatic creation of CheckSuite events upon pushes to the repository, or "false" to disable them. Default: "true" (Required.) } // CheckSuitePreferenceOptions set options for check suite preferences for a repository. type CheckSuitePreferenceOptions struct { AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository. } // CheckSuitePreferenceResults represents the results of the preference set operation. type CheckSuitePreferenceResults struct { Preferences *PreferenceList `json:"preferences,omitempty"` Repository *Repository `json:"repository,omitempty"` } // PreferenceList represents a list of auto trigger checks for repository type PreferenceList struct { AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository. } // 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 func (s *ChecksService) SetCheckSuitePreferences(ctx context.Context, owner, repo string, opt CheckSuitePreferenceOptions) (*CheckSuitePreferenceResults, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-suites/preferences", owner, repo) req, err := s.client.NewRequest("PATCH", u, opt) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) var checkSuitePrefResults *CheckSuitePreferenceResults resp, err := s.client.Do(ctx, req, &checkSuitePrefResults) if err != nil { return nil, resp, err } return checkSuitePrefResults, resp, nil } // CreateCheckSuiteOptions sets up parameters to manually create a check suites type CreateCheckSuiteOptions struct { HeadSHA string `json:"head_sha"` // The sha of the head commit. (Required.) HeadBranch *string `json:"head_branch,omitempty"` // The name of the head branch where the code changes are implemented. } // CreateCheckSuite manually creates a check suite for a repository. // // GitHub API docs: https://developer.github.com/v3/checks/suites/#create-a-check-suite func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string, opt CreateCheckSuiteOptions) (*CheckSuite, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-suites", owner, repo) req, err := s.client.NewRequest("POST", u, opt) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) checkSuite := new(CheckSuite) resp, err := s.client.Do(ctx, req, checkSuite) if err != nil { return nil, resp, err } return checkSuite, resp, nil } // 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 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) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } req.Header.Set("Accept", mediaTypeCheckRunsPreview) resp, err := s.client.Do(ctx, req, nil) return resp, err } go-github-28.1.1/github/checks_test.go000066400000000000000000000533151353501270500176100ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "net/http" "reflect" "testing" "time" ) func TestChecksService_GetCheckRun(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/check-runs/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) fmt.Fprint(w, `{ "id": 1, "name":"testCheckRun", "status": "completed", "conclusion": "neutral", "started_at": "2018-05-04T01:14:52Z", "completed_at": "2018-05-04T01:14:52Z"}`) }) checkRun, _, err := client.Checks.GetCheckRun(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Checks.GetCheckRun return error: %v", err) } startedAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z") completeAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z") want := &CheckRun{ ID: Int64(1), Status: String("completed"), Conclusion: String("neutral"), StartedAt: &Timestamp{startedAt}, CompletedAt: &Timestamp{completeAt}, Name: String("testCheckRun"), } if !reflect.DeepEqual(checkRun, want) { t.Errorf("Checks.GetCheckRun return %+v, want %+v", checkRun, want) } } func TestChecksService_GetCheckSuite(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/check-suites/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) fmt.Fprint(w, `{ "id": 1, "head_branch":"master", "head_sha": "deadbeef", "conclusion": "neutral", "before": "deadbeefb", "after": "deadbeefa", "status": "completed"}`) }) checkSuite, _, err := client.Checks.GetCheckSuite(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Checks.GetCheckSuite return error: %v", err) } want := &CheckSuite{ ID: Int64(1), HeadBranch: String("master"), HeadSHA: String("deadbeef"), AfterSHA: String("deadbeefa"), BeforeSHA: String("deadbeefb"), Status: String("completed"), Conclusion: String("neutral"), } if !reflect.DeepEqual(checkSuite, want) { t.Errorf("Checks.GetCheckSuite return %+v, want %+v", checkSuite, want) } } func TestChecksService_CreateCheckRun(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/check-runs", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) fmt.Fprint(w, `{ "id": 1, "name":"testCreateCheckRun", "head_sha":"deadbeef", "status": "in_progress", "conclusion": null, "started_at": "2018-05-04T01:14:52Z", "completed_at": null, "output":{"title": "Mighty test report", "summary":"", "text":""}}`) }) startedAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z") checkRunOpt := CreateCheckRunOptions{ HeadBranch: "master", Name: "testCreateCheckRun", HeadSHA: "deadbeef", Status: String("in_progress"), StartedAt: &Timestamp{startedAt}, Output: &CheckRunOutput{ Title: String("Mighty test report"), Summary: String(""), Text: String(""), }, } checkRun, _, err := client.Checks.CreateCheckRun(context.Background(), "o", "r", checkRunOpt) if err != nil { t.Errorf("Checks.CreateCheckRun return error: %v", err) } want := &CheckRun{ ID: Int64(1), Status: String("in_progress"), StartedAt: &Timestamp{startedAt}, HeadSHA: String("deadbeef"), Name: String("testCreateCheckRun"), Output: &CheckRunOutput{ Title: String("Mighty test report"), Summary: String(""), Text: String(""), }, } if !reflect.DeepEqual(checkRun, want) { t.Errorf("Checks.CreateCheckRun return %+v, want %+v", checkRun, want) } } func TestChecksService_ListCheckRunAnnotations(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/check-runs/1/annotations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) testFormValues(t, r, values{ "page": "1", }) fmt.Fprint(w, `[{ "path": "README.md", "blob_href": "https://github.com/octocat/Hello-World/blob/837db83be4137ca555d9a5598d0a1ea2987ecfee/README.md", "start_line": 2, "end_line": 2, "start_column": 1, "end_column": 5, "annotation_level": "warning", "message": "Check your spelling for 'banaas'.", "title": "Spell check", "raw_details": "Do you mean 'bananas' or 'banana'?"}]`, ) }) checkRunAnnotations, _, err := client.Checks.ListCheckRunAnnotations(context.Background(), "o", "r", 1, &ListOptions{Page: 1}) if err != nil { t.Errorf("Checks.ListCheckRunAnnotations return error: %v", err) } want := []*CheckRunAnnotation{{ Path: String("README.md"), BlobHRef: String("https://github.com/octocat/Hello-World/blob/837db83be4137ca555d9a5598d0a1ea2987ecfee/README.md"), StartLine: Int(2), EndLine: Int(2), StartColumn: Int(1), EndColumn: Int(5), AnnotationLevel: String("warning"), Message: String("Check your spelling for 'banaas'."), Title: String("Spell check"), RawDetails: String("Do you mean 'bananas' or 'banana'?"), }} if !reflect.DeepEqual(checkRunAnnotations, want) { t.Errorf("Checks.ListCheckRunAnnotations returned %+v, want %+v", checkRunAnnotations, want) } } func TestChecksService_UpdateCheckRun(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/check-runs/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) fmt.Fprint(w, `{ "id": 1, "name":"testUpdateCheckRun", "head_sha":"deadbeef", "status": "completed", "conclusion": "neutral", "started_at": "2018-05-04T01:14:52Z", "completed_at": "2018-05-04T01:14:52Z", "output":{"title": "Mighty test report", "summary":"There are 0 failures, 2 warnings and 1 notice", "text":"You may have misspelled some words."}}`) }) startedAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z") updateCheckRunOpt := UpdateCheckRunOptions{ HeadBranch: String("master"), Name: "testUpdateCheckRun", HeadSHA: String("deadbeef"), Status: String("completed"), CompletedAt: &Timestamp{startedAt}, Output: &CheckRunOutput{ Title: String("Mighty test report"), Summary: String("There are 0 failures, 2 warnings and 1 notice"), Text: String("You may have misspelled some words."), }, } checkRun, _, err := client.Checks.UpdateCheckRun(context.Background(), "o", "r", 1, updateCheckRunOpt) if err != nil { t.Errorf("Checks.UpdateCheckRun return error: %v", err) } want := &CheckRun{ ID: Int64(1), Status: String("completed"), StartedAt: &Timestamp{startedAt}, CompletedAt: &Timestamp{startedAt}, Conclusion: String("neutral"), HeadSHA: String("deadbeef"), Name: String("testUpdateCheckRun"), Output: &CheckRunOutput{ Title: String("Mighty test report"), Summary: String("There are 0 failures, 2 warnings and 1 notice"), Text: String("You may have misspelled some words."), }, } if !reflect.DeepEqual(checkRun, want) { t.Errorf("Checks.UpdateCheckRun return %+v, want %+v", checkRun, want) } } func TestChecksService_ListCheckRunsForRef(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/commits/master/check-runs", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) testFormValues(t, r, values{ "check_name": "testing", "page": "1", "status": "completed", "filter": "all", }) fmt.Fprint(w, `{"total_count":1, "check_runs": [{ "id": 1, "head_sha": "deadbeef", "status": "completed", "conclusion": "neutral", "started_at": "2018-05-04T01:14:52Z", "completed_at": "2018-05-04T01:14:52Z"}]}`, ) }) opt := &ListCheckRunsOptions{ CheckName: String("testing"), Status: String("completed"), Filter: String("all"), ListOptions: ListOptions{Page: 1}, } checkRuns, _, err := client.Checks.ListCheckRunsForRef(context.Background(), "o", "r", "master", opt) if err != nil { t.Errorf("Checks.ListCheckRunsForRef return error: %v", err) } startedAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z") want := &ListCheckRunsResults{ Total: Int(1), CheckRuns: []*CheckRun{{ ID: Int64(1), Status: String("completed"), StartedAt: &Timestamp{startedAt}, CompletedAt: &Timestamp{startedAt}, Conclusion: String("neutral"), HeadSHA: String("deadbeef"), }}, } if !reflect.DeepEqual(checkRuns, want) { t.Errorf("Checks.ListCheckRunsForRef returned %+v, want %+v", checkRuns, want) } } func TestChecksService_ListCheckRunsCheckSuite(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/check-suites/1/check-runs", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) testFormValues(t, r, values{ "check_name": "testing", "page": "1", "status": "completed", "filter": "all", }) fmt.Fprint(w, `{"total_count":1, "check_runs": [{ "id": 1, "head_sha": "deadbeef", "status": "completed", "conclusion": "neutral", "started_at": "2018-05-04T01:14:52Z", "completed_at": "2018-05-04T01:14:52Z"}]}`, ) }) opt := &ListCheckRunsOptions{ CheckName: String("testing"), Status: String("completed"), Filter: String("all"), ListOptions: ListOptions{Page: 1}, } checkRuns, _, err := client.Checks.ListCheckRunsCheckSuite(context.Background(), "o", "r", 1, opt) if err != nil { t.Errorf("Checks.ListCheckRunsCheckSuite return error: %v", err) } startedAt, _ := time.Parse(time.RFC3339, "2018-05-04T01:14:52Z") want := &ListCheckRunsResults{ Total: Int(1), CheckRuns: []*CheckRun{{ ID: Int64(1), Status: String("completed"), StartedAt: &Timestamp{startedAt}, CompletedAt: &Timestamp{startedAt}, Conclusion: String("neutral"), HeadSHA: String("deadbeef"), }}, } if !reflect.DeepEqual(checkRuns, want) { t.Errorf("Checks.ListCheckRunsCheckSuite returned %+v, want %+v", checkRuns, want) } } func TestChecksService_ListCheckSuiteForRef(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/commits/master/check-suites", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) testFormValues(t, r, values{ "check_name": "testing", "page": "1", "app_id": "2", }) fmt.Fprint(w, `{"total_count":1, "check_suites": [{ "id": 1, "head_sha": "deadbeef", "head_branch": "master", "status": "completed", "conclusion": "neutral", "before": "deadbeefb", "after": "deadbeefa"}]}`, ) }) opt := &ListCheckSuiteOptions{ CheckName: String("testing"), AppID: Int(2), ListOptions: ListOptions{Page: 1}, } checkSuites, _, err := client.Checks.ListCheckSuitesForRef(context.Background(), "o", "r", "master", opt) if err != nil { t.Errorf("Checks.ListCheckSuitesForRef return error: %v", err) } want := &ListCheckSuiteResults{ Total: Int(1), CheckSuites: []*CheckSuite{{ ID: Int64(1), Status: String("completed"), Conclusion: String("neutral"), HeadSHA: String("deadbeef"), HeadBranch: String("master"), BeforeSHA: String("deadbeefb"), AfterSHA: String("deadbeefa"), }}, } if !reflect.DeepEqual(checkSuites, want) { t.Errorf("Checks.ListCheckSuitesForRef returned %+v, want %+v", checkSuites, want) } } func TestChecksService_SetCheckSuitePreferences(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/check-suites/preferences", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) testBody(t, r, `{"auto_trigger_checks":[{"app_id":2,"setting":false}]}`+"\n") fmt.Fprint(w, `{"preferences":{"auto_trigger_checks":[{"app_id": 2,"setting": false}]}}`) }) a := []*AutoTriggerCheck{{ AppID: Int64(2), Setting: Bool(false), }} opt := CheckSuitePreferenceOptions{AutoTriggerChecks: a} prefResults, _, err := client.Checks.SetCheckSuitePreferences(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Checks.SetCheckSuitePreferences return error: %v", err) } p := &PreferenceList{ AutoTriggerChecks: a, } want := &CheckSuitePreferenceResults{ Preferences: p, } if !reflect.DeepEqual(prefResults, want) { t.Errorf("Checks.SetCheckSuitePreferences return %+v, want %+v", prefResults, want) } } func TestChecksService_CreateCheckSuite(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/check-suites", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) fmt.Fprint(w, `{ "id": 2, "head_branch":"master", "head_sha":"deadbeef", "status": "completed", "conclusion": "neutral", "before": "deadbeefb", "after": "deadbeefa"}`) }) checkSuiteOpt := CreateCheckSuiteOptions{ HeadSHA: "deadbeef", HeadBranch: String("master"), } checkSuite, _, err := client.Checks.CreateCheckSuite(context.Background(), "o", "r", checkSuiteOpt) if err != nil { t.Errorf("Checks.CreateCheckSuite return error: %v", err) } want := &CheckSuite{ ID: Int64(2), Status: String("completed"), HeadSHA: String("deadbeef"), HeadBranch: String("master"), Conclusion: String("neutral"), BeforeSHA: String("deadbeefb"), AfterSHA: String("deadbeefa"), } if !reflect.DeepEqual(checkSuite, want) { t.Errorf("Checks.CreateCheckSuite return %+v, want %+v", checkSuite, want) } } func TestChecksService_ReRequestCheckSuite(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/check-suites/1/rerequest", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeCheckRunsPreview) w.WriteHeader(http.StatusCreated) }) resp, err := client.Checks.ReRequestCheckSuite(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Checks.ReRequestCheckSuite return error: %v", err) } if got, want := resp.StatusCode, http.StatusCreated; got != want { t.Errorf("Checks.ReRequestCheckSuite = %v, want %v", got, want) } } func Test_CheckRunMarshal(t *testing.T) { testJSONMarshal(t, &CheckRun{}, "{}") now := time.Now() ts := now.Format(time.RFC3339Nano) c := CheckRun{ ID: Int64(1), NodeID: String("n"), HeadSHA: String("h"), ExternalID: String("1"), URL: String("u"), HTMLURL: String("u"), DetailsURL: String("u"), Status: String("s"), Conclusion: String("c"), StartedAt: &Timestamp{Time: now}, CompletedAt: &Timestamp{Time: now}, Output: &CheckRunOutput{ Annotations: []*CheckRunAnnotation{ { AnnotationLevel: String("a"), BlobHRef: String("b"), EndLine: Int(1), Message: String("m"), Path: String("p"), RawDetails: String("r"), StartLine: Int(1), Title: String("t"), }, }, AnnotationsCount: Int(1), AnnotationsURL: String("a"), Images: []*CheckRunImage{ { Alt: String("a"), ImageURL: String("i"), Caption: String("c"), }, }, Title: String("t"), Summary: String("s"), Text: String("t"), }, Name: String("n"), CheckSuite: &CheckSuite{ ID: Int64(1), }, App: &App{ ID: Int64(1), NodeID: String("n"), Owner: &User{ Login: String("l"), ID: Int64(1), NodeID: String("n"), URL: String("u"), ReposURL: String("r"), EventsURL: String("e"), AvatarURL: String("a"), }, Name: String("n"), Description: String("d"), HTMLURL: String("h"), ExternalURL: String("u"), CreatedAt: &Timestamp{now}, UpdatedAt: &Timestamp{now}, }, PullRequests: []*PullRequest{ { URL: String("u"), ID: Int64(1), Number: Int(1), Head: &PullRequestBranch{ Ref: String("r"), SHA: String("s"), Repo: &Repository{ ID: Int64(1), URL: String("s"), Name: String("n"), }, }, Base: &PullRequestBranch{ Ref: String("r"), SHA: String("s"), Repo: &Repository{ ID: Int64(1), URL: String("u"), Name: String("n"), }, }, }, }, } w := fmt.Sprintf(`{ "id": 1, "node_id": "n", "head_sha": "h", "external_id": "1", "url": "u", "html_url": "u", "details_url": "u", "status": "s", "conclusion": "c", "started_at": "%s", "completed_at": "%s", "output": { "title": "t", "summary": "s", "text": "t", "annotations_count": 1, "annotations_url": "a", "annotations": [ { "path": "p", "blob_href": "b", "start_line": 1, "end_line": 1, "annotation_level": "a", "message": "m", "title": "t", "raw_details": "r" } ], "images": [ { "alt": "a", "image_url": "i", "caption": "c" } ] }, "name": "n", "check_suite": { "id": 1 }, "app": { "id": 1, "node_id": "n", "owner": { "login": "l", "id": 1, "node_id": "n", "avatar_url": "a", "url": "u", "events_url": "e", "repos_url": "r" }, "name": "n", "description": "d", "external_url": "u", "html_url": "h", "created_at": "%s", "updated_at": "%s" }, "pull_requests": [ { "id": 1, "number": 1, "url": "u", "head": { "ref": "r", "sha": "s", "repo": { "id": 1, "name": "n", "url": "s" } }, "base": { "ref": "r", "sha": "s", "repo": { "id": 1, "name": "n", "url": "u" } } } ] }`, ts, ts, ts, ts) testJSONMarshal(t, &c, w) } func Test_CheckSuiteMarshal(t *testing.T) { testJSONMarshal(t, &CheckSuite{}, "{}") now := time.Now() ts := now.Format(time.RFC3339Nano) c := CheckSuite{ ID: Int64(1), NodeID: String("n"), HeadBranch: String("h"), HeadSHA: String("h"), URL: String("u"), BeforeSHA: String("b"), AfterSHA: String("a"), Status: String("s"), Conclusion: String("c"), App: &App{ ID: Int64(1), NodeID: String("n"), Owner: &User{ Login: String("l"), ID: Int64(1), NodeID: String("n"), URL: String("u"), ReposURL: String("r"), EventsURL: String("e"), AvatarURL: String("a"), }, Name: String("n"), Description: String("d"), HTMLURL: String("h"), ExternalURL: String("u"), CreatedAt: &Timestamp{now}, UpdatedAt: &Timestamp{now}, }, Repository: &Repository{ ID: Int64(1), }, PullRequests: []*PullRequest{ { URL: String("u"), ID: Int64(1), Number: Int(1), Head: &PullRequestBranch{ Ref: String("r"), SHA: String("s"), Repo: &Repository{ ID: Int64(1), URL: String("s"), Name: String("n"), }, }, Base: &PullRequestBranch{ Ref: String("r"), SHA: String("s"), Repo: &Repository{ ID: Int64(1), URL: String("u"), Name: String("n"), }, }, }, }, HeadCommit: &Commit{ SHA: String("s"), }, } w := fmt.Sprintf(`{ "id": 1, "node_id": "n", "head_branch": "h", "head_sha": "h", "url": "u", "before": "b", "after": "a", "status": "s", "conclusion": "c", "app": { "id": 1, "node_id": "n", "owner": { "login": "l", "id": 1, "node_id": "n", "avatar_url": "a", "url": "u", "events_url": "e", "repos_url": "r" }, "name": "n", "description": "d", "external_url": "u", "html_url": "h", "created_at": "%s", "updated_at": "%s" }, "repository": { "id": 1 }, "pull_requests": [ { "id": 1, "number": 1, "url": "u", "head": { "ref": "r", "sha": "s", "repo": { "id": 1, "name": "n", "url": "s" } }, "base": { "ref": "r", "sha": "s", "repo": { "id": 1, "name": "n", "url": "u" } } } ], "head_commit": { "sha": "s" } }`, ts, ts) testJSONMarshal(t, &c, w) } go-github-28.1.1/github/doc.go000066400000000000000000000150501353501270500160500ustar00rootroot00000000000000// 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 provides a client for using the GitHub API. Usage: import "github.com/google/go-github/v28/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) import "github.com/google/go-github/github" // with go modules disabled Construct a new GitHub client, then use the various services on the client to access different parts of the GitHub API. For example: client := github.NewClient(nil) // list all organizations for user "willnorris" orgs, _, err := client.Organizations.List(ctx, "willnorris", nil) Some API methods have optional parameters that can be passed. For example: client := github.NewClient(nil) // list public repositories for org "github" opt := &github.RepositoryListByOrgOptions{Type: "public"} repos, _, err := client.Repositories.ListByOrg(ctx, "github", opt) The services of a client divide the API into logical chunks and correspond to the structure of the GitHub API documentation at https://developer.github.com/v3/. NOTE: Using the https://godoc.org/context package, one can easily pass cancelation signals and deadlines to various services of the client for handling a request. In case there is no context available, then context.Background() can be used as a starting point. For more sample code snippets, head over to the https://github.com/google/go-github/tree/master/example directory. Authentication The go-github library does not directly handle authentication. Instead, when creating a new client, pass an http.Client that can handle authentication for you. The easiest and recommended way to do this is using the golang.org/x/oauth2 library, but you can always use any other library that provides an http.Client. If you have an OAuth2 access token (for example, a personal API token), you can use it with the oauth2 library using: import "golang.org/x/oauth2" func main() { ctx := context.Background() ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: "... your access token ..."}, ) tc := oauth2.NewClient(ctx, ts) client := github.NewClient(tc) // list all repositories for the authenticated user repos, _, err := client.Repositories.List(ctx, "", nil) } Note that when using an authenticated Client, all calls made by the client will include the specified OAuth token. Therefore, authenticated clients should almost never be shared between different users. See the oauth2 docs for complete instructions on using that library. For API methods that require HTTP Basic Authentication, use the BasicAuthTransport. GitHub Apps authentication can be provided by the https://github.com/bradleyfalzon/ghinstallation package. import "github.com/bradleyfalzon/ghinstallation" func main() { // Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99. itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "2016-10-19.private-key.pem") if err != nil { // Handle error. } // Use installation transport with client client := github.NewClient(&http.Client{Transport: itr}) // Use client... } Rate Limiting GitHub imposes a rate limit on all API clients. Unauthenticated clients are limited to 60 requests per hour, while authenticated clients can make up to 5,000 requests per hour. The Search API has a custom rate limit. Unauthenticated clients are limited to 10 requests per minute, while authenticated clients can make up to 30 requests per minute. To receive the higher rate limit when making calls that are not issued on behalf of a user, use UnauthenticatedRateLimitedTransport. The returned Response.Rate value contains the rate limit information from the most recent API call. If a recent enough response isn't available, you can use RateLimits to fetch the most up-to-date rate limit data for the client. To detect an API rate limit error, you can check if its type is *github.RateLimitError: repos, _, err := client.Repositories.List(ctx, "", nil) if _, ok := err.(*github.RateLimitError); ok { log.Println("hit rate limit") } Learn more about GitHub rate limiting at https://developer.github.com/v3/#rate-limiting. Accepted Status Some endpoints may return a 202 Accepted status code, meaning that the information required is not yet ready and was scheduled to be gathered on the GitHub side. Methods known to behave like this are documented specifying this behavior. To detect this condition of error, you can check if its type is *github.AcceptedError: stats, _, err := client.Repositories.ListContributorsStats(ctx, org, repo) if _, ok := err.(*github.AcceptedError); ok { log.Println("scheduled on GitHub side") } Conditional Requests The GitHub API has good support for conditional requests which will help prevent you from burning through your rate limit, as well as help speed up your application. go-github does not handle conditional requests directly, but is instead designed to work with a caching http.Transport. We recommend using https://github.com/gregjones/httpcache for that. Learn more about GitHub conditional requests at https://developer.github.com/v3/#conditional-requests. Creating and Updating Resources All structs for GitHub resources use pointer values for all non-repeated fields. This allows distinguishing between unset fields and those set to a zero-value. Helper functions have been provided to easily create these pointers for string, bool, and int values. For example: // create a new private repository named "foo" repo := &github.Repository{ Name: github.String("foo"), Private: github.Bool(true), } client.Repositories.Create(ctx, "", repo) Users who have worked with protocol buffers should find this pattern familiar. Pagination All requests for resource collections (repos, pull requests, issues, etc.) support pagination. Pagination options are described in the github.ListOptions struct and passed to the list methods directly or as an embedded type of a more specific list options struct (for example github.PullRequestListOptions). Pages information is available via the github.Response struct. client := github.NewClient(nil) opt := &github.RepositoryListByOrgOptions{ ListOptions: github.ListOptions{PerPage: 10}, } // get all pages of results var allRepos []*github.Repository for { repos, resp, err := client.Repositories.ListByOrg(ctx, "github", opt) if err != nil { return err } allRepos = append(allRepos, repos...) if resp.NextPage == 0 { break } opt.Page = resp.NextPage } */ package github go-github-28.1.1/github/event.go000066400000000000000000000073031353501270500164260ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "encoding/json" "time" ) // Event represents a GitHub event. type Event struct { Type *string `json:"type,omitempty"` Public *bool `json:"public,omitempty"` RawPayload *json.RawMessage `json:"payload,omitempty"` Repo *Repository `json:"repo,omitempty"` Actor *User `json:"actor,omitempty"` Org *Organization `json:"org,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` ID *string `json:"id,omitempty"` } func (e Event) String() string { return Stringify(e) } // ParsePayload parses the event payload. For recognized event types, // a value of the corresponding struct type will be returned. func (e *Event) ParsePayload() (payload interface{}, err error) { switch *e.Type { case "CheckRunEvent": payload = &CheckRunEvent{} case "CheckSuiteEvent": payload = &CheckSuiteEvent{} case "CommitCommentEvent": payload = &CommitCommentEvent{} case "CreateEvent": payload = &CreateEvent{} case "DeleteEvent": payload = &DeleteEvent{} case "DeployKeyEvent": payload = &DeployKeyEvent{} case "DeploymentEvent": payload = &DeploymentEvent{} case "DeploymentStatusEvent": payload = &DeploymentStatusEvent{} case "ForkEvent": payload = &ForkEvent{} case "GitHubAppAuthorizationEvent": payload = &GitHubAppAuthorizationEvent{} case "GollumEvent": payload = &GollumEvent{} case "InstallationEvent": payload = &InstallationEvent{} case "InstallationRepositoriesEvent": payload = &InstallationRepositoriesEvent{} case "IssueCommentEvent": payload = &IssueCommentEvent{} case "IssuesEvent": payload = &IssuesEvent{} case "LabelEvent": payload = &LabelEvent{} case "MarketplacePurchaseEvent": payload = &MarketplacePurchaseEvent{} case "MemberEvent": payload = &MemberEvent{} case "MembershipEvent": payload = &MembershipEvent{} case "MetaEvent": payload = &MetaEvent{} case "MilestoneEvent": payload = &MilestoneEvent{} case "OrganizationEvent": payload = &OrganizationEvent{} case "OrgBlockEvent": payload = &OrgBlockEvent{} case "PageBuildEvent": payload = &PageBuildEvent{} case "PingEvent": payload = &PingEvent{} case "ProjectEvent": payload = &ProjectEvent{} case "ProjectCardEvent": payload = &ProjectCardEvent{} case "ProjectColumnEvent": payload = &ProjectColumnEvent{} case "PublicEvent": payload = &PublicEvent{} case "PullRequestEvent": payload = &PullRequestEvent{} case "PullRequestReviewEvent": payload = &PullRequestReviewEvent{} case "PullRequestReviewCommentEvent": payload = &PullRequestReviewCommentEvent{} case "PushEvent": payload = &PushEvent{} case "ReleaseEvent": payload = &ReleaseEvent{} case "RepositoryEvent": payload = &RepositoryEvent{} case "RepositoryVulnerabilityAlertEvent": payload = &RepositoryVulnerabilityAlertEvent{} case "StarEvent": payload = &StarEvent{} case "StatusEvent": payload = &StatusEvent{} case "TeamEvent": payload = &TeamEvent{} case "TeamAddEvent": payload = &TeamAddEvent{} case "WatchEvent": payload = &WatchEvent{} } err = json.Unmarshal(*e.RawPayload, &payload) return payload, err } // Payload returns the parsed event payload. For recognized event types, // a value of the corresponding struct type will be returned. // // Deprecated: Use ParsePayload instead, which returns an error // rather than panics if JSON unmarshaling raw payload fails. func (e *Event) Payload() (payload interface{}) { var err error payload, err = e.ParsePayload() if err != nil { panic(err) } return payload } go-github-28.1.1/github/event_types.go000066400000000000000000001153111353501270500176510ustar00rootroot00000000000000// 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. // These event types are shared between the Events API and used as Webhook payloads. package github // RequestedAction is included in a CheckRunEvent when a user has invoked an action, // i.e. when the CheckRunEvent's Action field is "requested_action". type RequestedAction struct { Identifier string `json:"identifier"` // The integrator reference of the action requested by the user. } // CheckRunEvent is triggered when a check run is "created", "updated", or "rerequested". // The Webhook event name is "check_run". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#checkrunevent type CheckRunEvent struct { CheckRun *CheckRun `json:"check_run,omitempty"` // The action performed. Possible values are: "created", "updated", "rerequested" or "requested_action". Action *string `json:"action,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Org *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` // The action requested by the user. Populated when the Action is "requested_action". RequestedAction *RequestedAction `json:"requested_action,omitempty"` // } // CheckSuiteEvent is triggered when a check suite is "completed", "requested", or "rerequested". // The Webhook event name is "check_suite". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#checksuiteevent type CheckSuiteEvent struct { CheckSuite *CheckSuite `json:"check_suite,omitempty"` // The action performed. Possible values are: "completed", "requested" or "rerequested". Action *string `json:"action,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Org *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // CommitCommentEvent is triggered when a commit comment is created. // The Webhook event name is "commit_comment". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#commitcommentevent type CommitCommentEvent struct { Comment *RepositoryComment `json:"comment,omitempty"` // The following fields are only populated by Webhook events. Action *string `json:"action,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // CreateEvent represents a created repository, branch, or tag. // The Webhook event name is "create". // // Note: webhooks will not receive this event for created repositories. // Additionally, webhooks will not receive this event for tags if more // than three tags are pushed at once. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#createevent type CreateEvent struct { Ref *string `json:"ref,omitempty"` // RefType is the object that was created. Possible values are: "repository", "branch", "tag". RefType *string `json:"ref_type,omitempty"` MasterBranch *string `json:"master_branch,omitempty"` Description *string `json:"description,omitempty"` // The following fields are only populated by Webhook events. PusherType *string `json:"pusher_type,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // DeleteEvent represents a deleted branch or tag. // The Webhook event name is "delete". // // Note: webhooks will not receive this event for tags if more than three tags // are deleted at once. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#deleteevent type DeleteEvent struct { Ref *string `json:"ref,omitempty"` // RefType is the object that was deleted. Possible values are: "branch", "tag". RefType *string `json:"ref_type,omitempty"` // The following fields are only populated by Webhook events. PusherType *string `json:"pusher_type,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // DeployKeyEvent is triggered when a deploy key is added or removed from a repository. // The Webhook event name is "deploy_key". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploykeyevent type DeployKeyEvent struct { // Action is the action that was performed. Possible values are: // "created" or "deleted". Action *string `json:"action,omitempty"` // The deploy key resource. Key *Key `json:"key,omitempty"` } // DeploymentEvent represents a deployment. // The Webhook event name is "deployment". // // Events of this type are not visible in timelines, they are only used to trigger hooks. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploymentevent type DeploymentEvent struct { Deployment *Deployment `json:"deployment,omitempty"` Repo *Repository `json:"repository,omitempty"` // The following fields are only populated by Webhook events. Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // DeploymentStatusEvent represents a deployment status. // The Webhook event name is "deployment_status". // // Events of this type are not visible in timelines, they are only used to trigger hooks. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploymentstatusevent type DeploymentStatusEvent struct { Deployment *Deployment `json:"deployment,omitempty"` DeploymentStatus *DeploymentStatus `json:"deployment_status,omitempty"` Repo *Repository `json:"repository,omitempty"` // The following fields are only populated by Webhook events. Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // ForkEvent is triggered when a user forks a repository. // The Webhook event name is "fork". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#forkevent type ForkEvent struct { // Forkee is the created repository. Forkee *Repository `json:"forkee,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // GitHubAppAuthorizationEvent is triggered when a user's authorization for a // GitHub Application is revoked. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#githubappauthorizationevent type GitHubAppAuthorizationEvent struct { // The action performed. Possible value is: "revoked". Action *string `json:"action,omitempty"` // The following fields are only populated by Webhook events. Sender *User `json:"sender,omitempty"` } // Page represents a single Wiki page. type Page struct { PageName *string `json:"page_name,omitempty"` Title *string `json:"title,omitempty"` Summary *string `json:"summary,omitempty"` Action *string `json:"action,omitempty"` SHA *string `json:"sha,omitempty"` HTMLURL *string `json:"html_url,omitempty"` } // GollumEvent is triggered when a Wiki page is created or updated. // The Webhook event name is "gollum". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#gollumevent type GollumEvent struct { Pages []*Page `json:"pages,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // EditChange represents the changes when an issue, pull request, or comment has // been edited. type EditChange struct { Title *struct { From *string `json:"from,omitempty"` } `json:"title,omitempty"` Body *struct { From *string `json:"from,omitempty"` } `json:"body,omitempty"` } // ProjectChange represents the changes when a project has been edited. type ProjectChange struct { Name *struct { From *string `json:"from,omitempty"` } `json:"name,omitempty"` Body *struct { From *string `json:"from,omitempty"` } `json:"body,omitempty"` } // ProjectCardChange represents the changes when a project card has been edited. type ProjectCardChange struct { Note *struct { From *string `json:"from,omitempty"` } `json:"note,omitempty"` } // ProjectColumnChange represents the changes when a project column has been edited. type ProjectColumnChange struct { Name *struct { From *string `json:"from,omitempty"` } `json:"name,omitempty"` } // TeamChange represents the changes when a team has been edited. type TeamChange struct { Description *struct { From *string `json:"from,omitempty"` } `json:"description,omitempty"` Name *struct { From *string `json:"from,omitempty"` } `json:"name,omitempty"` Privacy *struct { From *string `json:"from,omitempty"` } `json:"privacy,omitempty"` Repository *struct { Permissions *struct { From *struct { Admin *bool `json:"admin,omitempty"` Pull *bool `json:"pull,omitempty"` Push *bool `json:"push,omitempty"` } `json:"from,omitempty"` } `json:"permissions,omitempty"` } `json:"repository,omitempty"` } // InstallationEvent is triggered when a GitHub App has been installed or uninstalled. // The Webhook event name is "installation". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#installationevent type InstallationEvent struct { // The action that was performed. Can be either "created" or "deleted". Action *string `json:"action,omitempty"` Repositories []*Repository `json:"repositories,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // InstallationRepositoriesEvent is triggered when a repository is added or // removed from an installation. The Webhook event name is "installation_repositories". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#installationrepositoriesevent type InstallationRepositoriesEvent struct { // The action that was performed. Can be either "added" or "removed". Action *string `json:"action,omitempty"` RepositoriesAdded []*Repository `json:"repositories_added,omitempty"` RepositoriesRemoved []*Repository `json:"repositories_removed,omitempty"` RepositorySelection *string `json:"repository_selection,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // IssueCommentEvent is triggered when an issue comment is created on an issue // or pull request. // The Webhook event name is "issue_comment". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuecommentevent type IssueCommentEvent struct { // Action is the action that was performed on the comment. // Possible values are: "created", "edited", "deleted". Action *string `json:"action,omitempty"` Issue *Issue `json:"issue,omitempty"` Comment *IssueComment `json:"comment,omitempty"` // The following fields are only populated by Webhook events. Changes *EditChange `json:"changes,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // IssuesEvent is triggered when an issue is opened, edited, deleted, transferred, // pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled, // locked, unlocked, milestoned, or demilestoned. // The Webhook event name is "issues". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuesevent type IssuesEvent struct { // Action is the action that was performed. Possible values are: "opened", // "edited", "deleted", "transferred", "pinned", "unpinned", "closed", "reopened", // "assigned", "unassigned", "labeled", "unlabeled", "locked", "unlocked", // "milestoned", or "demilestoned". Action *string `json:"action,omitempty"` Issue *Issue `json:"issue,omitempty"` Assignee *User `json:"assignee,omitempty"` Label *Label `json:"label,omitempty"` // The following fields are only populated by Webhook events. Changes *EditChange `json:"changes,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // LabelEvent is triggered when a repository's label is created, edited, or deleted. // The Webhook event name is "label" // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#labelevent type LabelEvent struct { // Action is the action that was performed. Possible values are: // "created", "edited", "deleted" Action *string `json:"action,omitempty"` Label *Label `json:"label,omitempty"` // The following fields are only populated by Webhook events. Changes *EditChange `json:"changes,omitempty"` Repo *Repository `json:"repository,omitempty"` Org *Organization `json:"organization,omitempty"` Installation *Installation `json:"installation,omitempty"` } // MarketplacePurchaseEvent is triggered when a user purchases, cancels, or changes // their GitHub Marketplace plan. // Webhook event name "marketplace_purchase". // // Github API docs: https://developer.github.com/v3/activity/events/types/#marketplacepurchaseevent type MarketplacePurchaseEvent struct { // Action is the action that was performed. Possible values are: // "purchased", "cancelled", "pending_change", "pending_change_cancelled", "changed". Action *string `json:"action,omitempty"` // The following fields are only populated by Webhook events. EffectiveDate *Timestamp `json:"effective_date,omitempty"` MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` PreviousMarketplacePurchase *MarketplacePurchase `json:"previous_marketplace_purchase,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // MemberEvent is triggered when a user is added as a collaborator to a repository. // The Webhook event name is "member". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#memberevent type MemberEvent struct { // Action is the action that was performed. Possible value is: "added". Action *string `json:"action,omitempty"` Member *User `json:"member,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // MembershipEvent is triggered when a user is added or removed from a team. // The Webhook event name is "membership". // // Events of this type are not visible in timelines, they are only used to // trigger organization webhooks. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#membershipevent type MembershipEvent struct { // Action is the action that was performed. Possible values are: "added", "removed". Action *string `json:"action,omitempty"` // Scope is the scope of the membership. Possible value is: "team". Scope *string `json:"scope,omitempty"` Member *User `json:"member,omitempty"` Team *Team `json:"team,omitempty"` // The following fields are only populated by Webhook events. Org *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // MetaEvent is triggered when the webhook that this event is configured on is deleted. // This event will only listen for changes to the particular hook the event is installed on. // Therefore, it must be selected for each hook that you'd like to receive meta events for. // The Webhook event name is "meta". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#metaevent type MetaEvent struct { // Action is the action that was performed. Possible value is: "deleted". Action *string `json:"action,omitempty"` // The ID of the modified webhook. HookID *int64 `json:"hook_id,omitempty"` // The modified webhook. // This will contain different keys based on the type of webhook it is: repository, // organization, business, app, or GitHub Marketplace. Hook *Hook `json:"hook,omitempty"` } // MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted. // The Webhook event name is "milestone". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#milestoneevent type MilestoneEvent struct { // Action is the action that was performed. Possible values are: // "created", "closed", "opened", "edited", "deleted" Action *string `json:"action,omitempty"` Milestone *Milestone `json:"milestone,omitempty"` // The following fields are only populated by Webhook events. Changes *EditChange `json:"changes,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Org *Organization `json:"organization,omitempty"` Installation *Installation `json:"installation,omitempty"` } // OrganizationEvent is triggered when an organization is deleted and renamed, and when a user is added, // removed, or invited to an organization. // Events of this type are not visible in timelines. These events are only used to trigger organization hooks. // Webhook event name is "organization". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#organizationevent type OrganizationEvent struct { // Action is the action that was performed. // Possible values are: "deleted", "renamed", "member_added", "member_removed", or "member_invited". Action *string `json:"action,omitempty"` // Invitation is the invitation for the user or email if the action is "member_invited". Invitation *Invitation `json:"invitation,omitempty"` // Membership is the membership between the user and the organization. // Not present when the action is "member_invited". Membership *Membership `json:"membership,omitempty"` Organization *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // OrgBlockEvent is triggered when an organization blocks or unblocks a user. // The Webhook event name is "org_block". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#orgblockevent type OrgBlockEvent struct { // Action is the action that was performed. // Can be "blocked" or "unblocked". Action *string `json:"action,omitempty"` BlockedUser *User `json:"blocked_user,omitempty"` Organization *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` // The following fields are only populated by Webhook events. Installation *Installation `json:"installation,omitempty"` } // PageBuildEvent represents an attempted build of a GitHub Pages site, whether // successful or not. // The Webhook event name is "page_build". // // This event is triggered on push to a GitHub Pages enabled branch (gh-pages // for project pages, master for user and organization pages). // // Events of this type are not visible in timelines, they are only used to trigger hooks. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#pagebuildevent type PageBuildEvent struct { Build *PagesBuild `json:"build,omitempty"` // The following fields are only populated by Webhook events. ID *int64 `json:"id,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // PingEvent is triggered when a Webhook is added to GitHub. // // GitHub API docs: https://developer.github.com/webhooks/#ping-event type PingEvent struct { // Random string of GitHub zen. Zen *string `json:"zen,omitempty"` // The ID of the webhook that triggered the ping. HookID *int64 `json:"hook_id,omitempty"` // The webhook configuration. Hook *Hook `json:"hook,omitempty"` Installation *Installation `json:"installation,omitempty"` } // ProjectEvent is triggered when project is created, modified or deleted. // The webhook event name is "project". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectevent type ProjectEvent struct { Action *string `json:"action,omitempty"` Changes *ProjectChange `json:"changes,omitempty"` Project *Project `json:"project,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Org *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // ProjectCardEvent is triggered when a project card is created, updated, moved, converted to an issue, or deleted. // The webhook event name is "project_card". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectcardevent type ProjectCardEvent struct { Action *string `json:"action,omitempty"` Changes *ProjectCardChange `json:"changes,omitempty"` AfterID *int64 `json:"after_id,omitempty"` ProjectCard *ProjectCard `json:"project_card,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Org *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // ProjectColumnEvent is triggered when a project column is created, updated, moved, or deleted. // The webhook event name is "project_column". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectcolumnevent type ProjectColumnEvent struct { Action *string `json:"action,omitempty"` Changes *ProjectColumnChange `json:"changes,omitempty"` AfterID *int64 `json:"after_id,omitempty"` ProjectColumn *ProjectColumn `json:"project_column,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Org *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // PublicEvent is triggered when a private repository is open sourced. // According to GitHub: "Without a doubt: the best GitHub event." // The Webhook event name is "public". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#publicevent type PublicEvent struct { // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // PullRequestEvent is triggered when a pull request is assigned, unassigned, labeled, // unlabeled, opened, edited, closed, reopened, synchronize, ready_for_review, // locked, unlocked, a pull request review is requested, or a review request is removed. // The Webhook event name is "pull_request". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestevent type PullRequestEvent struct { // Action is the action that was performed. Possible values are: // "assigned", "unassigned", "review_requested", "review_request_removed", "labeled", "unlabeled", // "opened", "edited", "closed", "ready_for_review", "locked", "unlocked", or "reopened". // If the action is "closed" and the "merged" key is "false", the pull request was closed with unmerged commits. // If the action is "closed" and the "merged" key is "true", the pull request was merged. // While webhooks are also triggered when a pull request is synchronized, Events API timelines // don't include pull request events with the "synchronize" action. Action *string `json:"action,omitempty"` Assignee *User `json:"assignee,omitempty"` Number *int `json:"number,omitempty"` PullRequest *PullRequest `json:"pull_request,omitempty"` // The following fields are only populated by Webhook events. Changes *EditChange `json:"changes,omitempty"` // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries. // A request affecting multiple reviewers at once is split into multiple // such event deliveries, each with a single, different RequestedReviewer. RequestedReviewer *User `json:"requested_reviewer,omitempty"` // In the event that a team is requested instead of a user, "requested_team" gets sent in place of // "requested_user" with the same delivery behavior. RequestedTeam *Team `json:"requested_team,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries. // The following field is only present when the webhook is triggered on // a repository belonging to an organization. Organization *Organization `json:"organization,omitempty"` } // PullRequestReviewEvent is triggered when a review is submitted on a pull // request. // The Webhook event name is "pull_request_review". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestreviewevent type PullRequestReviewEvent struct { // Action is always "submitted". Action *string `json:"action,omitempty"` Review *PullRequestReview `json:"review,omitempty"` PullRequest *PullRequest `json:"pull_request,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` // The following field is only present when the webhook is triggered on // a repository belonging to an organization. Organization *Organization `json:"organization,omitempty"` } // PullRequestReviewCommentEvent is triggered when a comment is created on a // portion of the unified diff of a pull request. // The Webhook event name is "pull_request_review_comment". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestreviewcommentevent type PullRequestReviewCommentEvent struct { // Action is the action that was performed on the comment. // Possible values are: "created", "edited", "deleted". Action *string `json:"action,omitempty"` PullRequest *PullRequest `json:"pull_request,omitempty"` Comment *PullRequestComment `json:"comment,omitempty"` // The following fields are only populated by Webhook events. Changes *EditChange `json:"changes,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // PushEvent represents a git push to a GitHub repository. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#pushevent type PushEvent struct { PushID *int64 `json:"push_id,omitempty"` Head *string `json:"head,omitempty"` Ref *string `json:"ref,omitempty"` Size *int `json:"size,omitempty"` Commits []PushEventCommit `json:"commits,omitempty"` Before *string `json:"before,omitempty"` DistinctSize *int `json:"distinct_size,omitempty"` // The following fields are only populated by Webhook events. After *string `json:"after,omitempty"` Created *bool `json:"created,omitempty"` Deleted *bool `json:"deleted,omitempty"` Forced *bool `json:"forced,omitempty"` BaseRef *string `json:"base_ref,omitempty"` Compare *string `json:"compare,omitempty"` Repo *PushEventRepository `json:"repository,omitempty"` HeadCommit *PushEventCommit `json:"head_commit,omitempty"` Pusher *User `json:"pusher,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } func (p PushEvent) String() string { return Stringify(p) } // PushEventCommit represents a git commit in a GitHub PushEvent. type PushEventCommit struct { Message *string `json:"message,omitempty"` Author *CommitAuthor `json:"author,omitempty"` URL *string `json:"url,omitempty"` Distinct *bool `json:"distinct,omitempty"` // The following fields are only populated by Events API. SHA *string `json:"sha,omitempty"` // The following fields are only populated by Webhook events. ID *string `json:"id,omitempty"` TreeID *string `json:"tree_id,omitempty"` Timestamp *Timestamp `json:"timestamp,omitempty"` Committer *CommitAuthor `json:"committer,omitempty"` Added []string `json:"added,omitempty"` Removed []string `json:"removed,omitempty"` Modified []string `json:"modified,omitempty"` } func (p PushEventCommit) String() string { return Stringify(p) } // PushEventRepository represents the repo object in a PushEvent payload. type PushEventRepository struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` Name *string `json:"name,omitempty"` FullName *string `json:"full_name,omitempty"` Owner *User `json:"owner,omitempty"` Private *bool `json:"private,omitempty"` Description *string `json:"description,omitempty"` Fork *bool `json:"fork,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` PushedAt *Timestamp `json:"pushed_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` Homepage *string `json:"homepage,omitempty"` PullsURL *string `json:"pulls_url,omitempty"` Size *int `json:"size,omitempty"` StargazersCount *int `json:"stargazers_count,omitempty"` WatchersCount *int `json:"watchers_count,omitempty"` Language *string `json:"language,omitempty"` HasIssues *bool `json:"has_issues,omitempty"` HasDownloads *bool `json:"has_downloads,omitempty"` HasWiki *bool `json:"has_wiki,omitempty"` HasPages *bool `json:"has_pages,omitempty"` ForksCount *int `json:"forks_count,omitempty"` OpenIssuesCount *int `json:"open_issues_count,omitempty"` DefaultBranch *string `json:"default_branch,omitempty"` MasterBranch *string `json:"master_branch,omitempty"` Organization *string `json:"organization,omitempty"` URL *string `json:"url,omitempty"` ArchiveURL *string `json:"archive_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` StatusesURL *string `json:"statuses_url,omitempty"` GitURL *string `json:"git_url,omitempty"` SSHURL *string `json:"ssh_url,omitempty"` CloneURL *string `json:"clone_url,omitempty"` SVNURL *string `json:"svn_url,omitempty"` } // PushEventRepoOwner is a basic representation of user/org in a PushEvent payload. type PushEventRepoOwner struct { Name *string `json:"name,omitempty"` Email *string `json:"email,omitempty"` } // ReleaseEvent is triggered when a release is published, unpublished, created, // edited, deleted, or prerelased. // The Webhook event name is "release". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#releaseevent type ReleaseEvent struct { // Action is the action that was performed. Possible values are: "published", "unpublished", // "created", "edited", "deleted", or "prereleased". Action *string `json:"action,omitempty"` Release *RepositoryRelease `json:"release,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // RepositoryEvent is triggered when a repository is created, archived, unarchived, // renamed, edited, transferred, made public, or made private. Organization hooks are // also trigerred when a repository is deleted. // The Webhook event name is "repository". // // Events of this type are not visible in timelines, they are only used to // trigger organization webhooks. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryevent type RepositoryEvent struct { // Action is the action that was performed. Possible values are: "created", // "deleted" (organization hooks only), "archived", "unarchived", "edited", "renamed", // "transferred", "publicized", or "privatized". Action *string `json:"action,omitempty"` Repo *Repository `json:"repository,omitempty"` // The following fields are only populated by Webhook events. Org *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // RepositoryVulnerabilityAlertEvent is triggered when a security alert is created, dismissed, or resolved. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryvulnerabilityalertevent type RepositoryVulnerabilityAlertEvent struct { // Action is the action that was performed. Possible values are: "create", "dismiss", "resolve". Action *string `json:"action,omitempty"` //The security alert of the vulnerable dependency. Alert *struct { ID *int64 `json:"id,omitempty"` AffectedRange *string `json:"affected_range,omitempty"` AffectedPackageName *string `json:"affected_package_name,omitempty"` ExternalReference *string `json:"external_reference,omitempty"` ExternalIdentifier *string `json:"external_identifier,omitempty"` FixedIn *string `json:"fixed_in,omitempty"` Dismisser *User `json:"dismisser,omitempty"` DismissReason *string `json:"dismiss_reason,omitempty"` DismissedAt *Timestamp `json:"dismissed_at,omitempty"` } `json:"alert,omitempty"` } // StarEvent is triggered when a star is added or removed from a repository. // The Webhook event name is "star". // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#starevent type StarEvent struct { // Action is the action that was performed. Possible values are: "created" or "deleted". Action *string `json:"action,omitempty"` // StarredAt is the time the star was created. It will be null for the "deleted" action. StarredAt *Timestamp `json:"starred_at,omitempty"` } // StatusEvent is triggered when the status of a Git commit changes. // The Webhook event name is "status". // // Events of this type are not visible in timelines, they are only used to // trigger hooks. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#statusevent type StatusEvent struct { SHA *string `json:"sha,omitempty"` // State is the new state. Possible values are: "pending", "success", "failure", "error". State *string `json:"state,omitempty"` Description *string `json:"description,omitempty"` TargetURL *string `json:"target_url,omitempty"` Branches []*Branch `json:"branches,omitempty"` // The following fields are only populated by Webhook events. ID *int64 `json:"id,omitempty"` Name *string `json:"name,omitempty"` Context *string `json:"context,omitempty"` Commit *RepositoryCommit `json:"commit,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // TeamEvent is triggered when an organization's team is created, modified or deleted. // The Webhook event name is "team". // // Events of this type are not visible in timelines. These events are only used // to trigger hooks. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#teamevent type TeamEvent struct { Action *string `json:"action,omitempty"` Team *Team `json:"team,omitempty"` Changes *TeamChange `json:"changes,omitempty"` Repo *Repository `json:"repository,omitempty"` // The following fields are only populated by Webhook events. Org *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // TeamAddEvent is triggered when a repository is added to a team. // The Webhook event name is "team_add". // // Events of this type are not visible in timelines. These events are only used // to trigger hooks. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#teamaddevent type TeamAddEvent struct { Team *Team `json:"team,omitempty"` Repo *Repository `json:"repository,omitempty"` // The following fields are only populated by Webhook events. Org *Organization `json:"organization,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } // WatchEvent is related to starring a repository, not watching. See this API // blog post for an explanation: https://developer.github.com/changes/2012-09-05-watcher-api/ // // The event’s actor is the user who starred a repository, and the event’s // repository is the repository that was starred. // // GitHub API docs: https://developer.github.com/v3/activity/events/types/#watchevent type WatchEvent struct { // Action is the action that was performed. Possible value is: "started". Action *string `json:"action,omitempty"` // The following fields are only populated by Webhook events. Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` Installation *Installation `json:"installation,omitempty"` } go-github-28.1.1/github/examples_test.go000066400000000000000000000120741353501270500201630ustar00rootroot00000000000000// 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. // These examples are inlined in godoc. package github_test import ( "context" "fmt" "log" "github.com/google/go-github/v28/github" ) func ExampleClient_Markdown() { client := github.NewClient(nil) input := "# heading #\n\nLink to issue #1" opt := &github.MarkdownOptions{Mode: "gfm", Context: "google/go-github"} output, _, err := client.Markdown(context.Background(), input, opt) if err != nil { fmt.Println(err) } fmt.Println(output) } func ExampleRepositoriesService_GetReadme() { client := github.NewClient(nil) readme, _, err := client.Repositories.GetReadme(context.Background(), "google", "go-github", nil) if err != nil { fmt.Println(err) return } content, err := readme.GetContent() if err != nil { fmt.Println(err) return } fmt.Printf("google/go-github README:\n%v\n", content) } func ExampleRepositoriesService_List() { client := github.NewClient(nil) user := "willnorris" opt := &github.RepositoryListOptions{Type: "owner", Sort: "updated", Direction: "desc"} repos, _, err := client.Repositories.List(context.Background(), user, opt) if err != nil { fmt.Println(err) } fmt.Printf("Recently updated repositories by %q: %v", user, github.Stringify(repos)) } func ExampleRepositoriesService_CreateFile() { // In this example we're creating a new file in a repository using the // Contents API. Only 1 file per commit can be managed through that API. // Note that authentication is needed here as you are performing a modification // so you will need to modify the example to provide an oauth client to // github.NewClient() instead of nil. See the following documentation for more // information on how to authenticate with the client: // https://godoc.org/github.com/google/go-github/github#hdr-Authentication client := github.NewClient(nil) ctx := context.Background() fileContent := []byte("This is the content of my file\nand the 2nd line of it") // Note: the file needs to be absent from the repository as you are not // specifying a SHA reference here. opts := &github.RepositoryContentFileOptions{ Message: github.String("This is my commit message"), Content: fileContent, Branch: github.String("master"), Committer: &github.CommitAuthor{Name: github.String("FirstName LastName"), Email: github.String("user@example.com")}, } _, _, err := client.Repositories.CreateFile(ctx, "myOrganization", "myRepository", "myNewFile.md", opts) if err != nil { fmt.Println(err) return } } func ExampleUsersService_ListAll() { client := github.NewClient(nil) opts := &github.UserListOptions{} for { users, _, err := client.Users.ListAll(context.Background(), opts) if err != nil { log.Fatalf("error listing users: %v", err) } if len(users) == 0 { break } opts.Since = *users[len(users)-1].ID // Process users... } } func ExamplePullRequestsService_Create() { // In this example we're creating a PR and displaying the HTML url at the end. // Note that authentication is needed here as you are performing a modification // so you will need to modify the example to provide an oauth client to // github.NewClient() instead of nil. See the following documentation for more // information on how to authenticate with the client: // https://godoc.org/github.com/google/go-github/github#hdr-Authentication client := github.NewClient(nil) newPR := &github.NewPullRequest{ Title: github.String("My awesome pull request"), Head: github.String("branch_to_merge"), Base: github.String("master"), Body: github.String("This is the description of the PR created with the package `github.com/google/go-github/github`"), MaintainerCanModify: github.Bool(true), } pr, _, err := client.PullRequests.Create(context.Background(), "myOrganization", "myRepository", newPR) if err != nil { fmt.Println(err) return } fmt.Printf("PR created: %s\n", pr.GetHTMLURL()) } func ExampleTeamsService_ListTeams() { // This example shows how to get a team ID corresponding to a given team name. // Note that authentication is needed here as you are performing a lookup on // an organization's administrative configuration, so you will need to modify // the example to provide an oauth client to github.NewClient() instead of nil. // See the following documentation for more information on how to authenticate // with the client: // https://godoc.org/github.com/google/go-github/github#hdr-Authentication client := github.NewClient(nil) teamName := "Developers team" ctx := context.Background() opts := &github.ListOptions{} for { teams, resp, err := client.Teams.ListTeams(ctx, "myOrganization", opts) if err != nil { fmt.Println(err) return } for _, t := range teams { if t.GetName() == teamName { fmt.Printf("Team %q has ID %d\n", teamName, t.GetID()) return } } if resp.NextPage == 0 { break } opts.Page = resp.NextPage } fmt.Printf("Team %q was not found\n", teamName) } go-github-28.1.1/github/gen-accessors.go000066400000000000000000000206541353501270500200450ustar00rootroot00000000000000// Copyright 2017 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-accessors generates accessor methods for structs with pointer fields. // // 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 ( "bytes" "flag" "fmt" "go/ast" "go/format" "go/parser" "go/token" "io/ioutil" "log" "os" "sort" "strings" "text/template" ) const ( fileSuffix = "-accessors.go" ) var ( verbose = flag.Bool("v", false, "Print verbose log messages") sourceTmpl = template.Must(template.New("source").Parse(source)) // blacklistStructMethod lists "struct.method" combos to skip. blacklistStructMethod = map[string]bool{ "RepositoryContent.GetContent": true, "Client.GetBaseURL": true, "Client.GetUploadURL": true, "ErrorResponse.GetResponse": true, "RateLimitError.GetResponse": true, "AbuseRateLimitError.GetResponse": true, } // blacklistStruct lists structs to skip. blacklistStruct = map[string]bool{ "Client": true, } ) func logf(fmt string, args ...interface{}) { if *verbose { log.Printf(fmt, args...) } } func main() { flag.Parse() fset := token.NewFileSet() pkgs, err := parser.ParseDir(fset, ".", sourceFilter, 0) if err != nil { log.Fatal(err) return } for pkgName, pkg := range pkgs { t := &templateData{ filename: pkgName + fileSuffix, Year: 2017, Package: pkgName, Imports: map[string]string{}, } for filename, f := range pkg.Files { logf("Processing %v...", filename) if err := t.processAST(f); err != nil { log.Fatal(err) } } if err := t.dump(); err != nil { log.Fatal(err) } } logf("Done.") } func (t *templateData) processAST(f *ast.File) error { for _, decl := range f.Decls { gd, ok := decl.(*ast.GenDecl) if !ok { continue } for _, spec := range gd.Specs { ts, ok := spec.(*ast.TypeSpec) if !ok { continue } // Skip unexported identifiers. if !ts.Name.IsExported() { logf("Struct %v is unexported; skipping.", ts.Name) continue } // Check if the struct is blacklisted. if blacklistStruct[ts.Name.Name] { logf("Struct %v is blacklisted; skipping.", ts.Name) continue } st, ok := ts.Type.(*ast.StructType) if !ok { continue } for _, field := range st.Fields.List { se, ok := field.Type.(*ast.StarExpr) if len(field.Names) == 0 || !ok { continue } fieldName := field.Names[0] // Skip unexported identifiers. if !fieldName.IsExported() { logf("Field %v is unexported; skipping.", fieldName) continue } // Check if "struct.method" is blacklisted. if key := fmt.Sprintf("%v.Get%v", ts.Name, fieldName); blacklistStructMethod[key] { logf("Method %v is blacklisted; skipping.", key) continue } switch x := se.X.(type) { case *ast.ArrayType: t.addArrayType(x, ts.Name.String(), fieldName.String()) case *ast.Ident: t.addIdent(x, ts.Name.String(), fieldName.String()) case *ast.MapType: t.addMapType(x, ts.Name.String(), fieldName.String()) case *ast.SelectorExpr: t.addSelectorExpr(x, ts.Name.String(), fieldName.String()) default: logf("processAST: type %q, field %q, unknown %T: %+v", ts.Name, fieldName, x, x) } } } } return nil } func sourceFilter(fi os.FileInfo) bool { return !strings.HasSuffix(fi.Name(), "_test.go") && !strings.HasSuffix(fi.Name(), fileSuffix) } func (t *templateData) dump() error { if len(t.Getters) == 0 { logf("No getters for %v; skipping.", t.filename) return nil } // Sort getters by ReceiverType.FieldName. sort.Sort(byName(t.Getters)) var buf bytes.Buffer if err := sourceTmpl.Execute(&buf, t); err != nil { return err } clean, err := format.Source(buf.Bytes()) if err != nil { return err } logf("Writing %v...", t.filename) return ioutil.WriteFile(t.filename, clean, 0644) } func newGetter(receiverType, fieldName, fieldType, zeroValue string, namedStruct bool) *getter { return &getter{ sortVal: strings.ToLower(receiverType) + "." + strings.ToLower(fieldName), ReceiverVar: strings.ToLower(receiverType[:1]), ReceiverType: receiverType, FieldName: fieldName, FieldType: fieldType, ZeroValue: zeroValue, NamedStruct: namedStruct, } } func (t *templateData) addArrayType(x *ast.ArrayType, receiverType, fieldName string) { var eltType string switch elt := x.Elt.(type) { case *ast.Ident: eltType = elt.String() default: logf("addArrayType: type %q, field %q: unknown elt type: %T %+v; skipping.", receiverType, fieldName, elt, elt) return } t.Getters = append(t.Getters, newGetter(receiverType, fieldName, "[]"+eltType, "nil", false)) } func (t *templateData) addIdent(x *ast.Ident, receiverType, fieldName string) { var zeroValue string var namedStruct = false switch x.String() { case "int", "int64": zeroValue = "0" case "string": zeroValue = `""` case "bool": zeroValue = "false" case "Timestamp": zeroValue = "Timestamp{}" default: zeroValue = "nil" namedStruct = true } t.Getters = append(t.Getters, newGetter(receiverType, fieldName, x.String(), zeroValue, namedStruct)) } func (t *templateData) addMapType(x *ast.MapType, receiverType, fieldName string) { var keyType string switch key := x.Key.(type) { case *ast.Ident: keyType = key.String() default: logf("addMapType: type %q, field %q: unknown key type: %T %+v; skipping.", receiverType, fieldName, key, key) return } var valueType string switch value := x.Value.(type) { case *ast.Ident: valueType = value.String() default: logf("addMapType: type %q, field %q: unknown value type: %T %+v; skipping.", receiverType, fieldName, value, value) return } fieldType := fmt.Sprintf("map[%v]%v", keyType, valueType) zeroValue := fmt.Sprintf("map[%v]%v{}", keyType, valueType) t.Getters = append(t.Getters, newGetter(receiverType, fieldName, fieldType, zeroValue, false)) } func (t *templateData) addSelectorExpr(x *ast.SelectorExpr, receiverType, fieldName string) { if strings.ToLower(fieldName[:1]) == fieldName[:1] { // Non-exported field. return } var xX string if xx, ok := x.X.(*ast.Ident); ok { xX = xx.String() } switch xX { case "time", "json": if xX == "json" { t.Imports["encoding/json"] = "encoding/json" } else { t.Imports[xX] = xX } fieldType := fmt.Sprintf("%v.%v", xX, x.Sel.Name) zeroValue := fmt.Sprintf("%v.%v{}", xX, x.Sel.Name) if xX == "time" && x.Sel.Name == "Duration" { zeroValue = "0" } t.Getters = append(t.Getters, newGetter(receiverType, fieldName, fieldType, zeroValue, false)) default: logf("addSelectorExpr: xX %q, type %q, field %q: unknown x=%+v; skipping.", xX, receiverType, fieldName, x) } } type templateData struct { filename string Year int Package string Imports map[string]string Getters []*getter } type getter struct { sortVal string // Lower-case version of "ReceiverType.FieldName". ReceiverVar string // The one-letter variable name to match the ReceiverType. ReceiverType string FieldName string FieldType string ZeroValue string NamedStruct bool // Getter for named struct. } type byName []*getter func (b byName) Len() int { return len(b) } func (b byName) Less(i, j int) bool { return b[i].sortVal < b[j].sortVal } func (b byName) Swap(i, j int) { b[i], b[j] = b[j], b[i] } const source = `// Copyright {{.Year}} 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. // Code generated by gen-accessors; DO NOT EDIT. package {{.Package}} {{with .Imports}} import ( {{- range . -}} "{{.}}" {{end -}} ) {{end}} {{range .Getters}} {{if .NamedStruct}} // Get{{.FieldName}} returns the {{.FieldName}} field. func ({{.ReceiverVar}} *{{.ReceiverType}}) Get{{.FieldName}}() *{{.FieldType}} { if {{.ReceiverVar}} == nil { return {{.ZeroValue}} } return {{.ReceiverVar}}.{{.FieldName}} } {{else}} // Get{{.FieldName}} returns the {{.FieldName}} field if it's non-nil, zero value otherwise. func ({{.ReceiverVar}} *{{.ReceiverType}}) Get{{.FieldName}}() {{.FieldType}} { if {{.ReceiverVar}} == nil || {{.ReceiverVar}}.{{.FieldName}} == nil { return {{.ZeroValue}} } return *{{.ReceiverVar}}.{{.FieldName}} } {{end}} {{end}} ` go-github-28.1.1/github/gen-stringify-test.go000066400000000000000000000221361353501270500210500ustar00rootroot00000000000000// Copyright 2019 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build ignore // gen-stringify-test generates test methods to test the String methods. // // These tests eliminate most of the code coverage problems so that real // code coverage issues can be more readily identified. // // 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 ( "bytes" "flag" "fmt" "go/ast" "go/format" "go/parser" "go/token" "io/ioutil" "log" "os" "strings" "text/template" ) const ( ignoreFilePrefix1 = "gen-" ignoreFilePrefix2 = "github-" outputFileSuffix = "-stringify_test.go" ) var ( verbose = flag.Bool("v", false, "Print verbose log messages") // blacklistStructMethod lists "struct.method" combos to skip. blacklistStructMethod = map[string]bool{} // blacklistStruct lists structs to skip. blacklistStruct = map[string]bool{ "RateLimits": true, } funcMap = template.FuncMap{ "isNotLast": func(index int, slice []*structField) string { if index+1 < len(slice) { return ", " } return "" }, "processZeroValue": func(v string) string { switch v { case "Bool(false)": return "false" case "Float64(0.0)": return "0" case "0", "Int(0)", "Int64(0)": return "0" case `""`, `String("")`: return `""` case "Timestamp{}", "&Timestamp{}": return "github.Timestamp{0001-01-01 00:00:00 +0000 UTC}" case "nil": return "map[]" } log.Fatalf("Unhandled zero value: %q", v) return "" }, } sourceTmpl = template.Must(template.New("source").Funcs(funcMap).Parse(source)) ) func main() { flag.Parse() fset := token.NewFileSet() pkgs, err := parser.ParseDir(fset, ".", sourceFilter, 0) if err != nil { log.Fatal(err) return } for pkgName, pkg := range pkgs { t := &templateData{ filename: pkgName + outputFileSuffix, Year: 2019, // No need to change this once set (even in following years). Package: pkgName, Imports: map[string]string{"testing": "testing"}, StringFuncs: map[string]bool{}, StructFields: map[string][]*structField{}, } for filename, f := range pkg.Files { logf("Processing %v...", filename) if err := t.processAST(f); err != nil { log.Fatal(err) } } if err := t.dump(); err != nil { log.Fatal(err) } } logf("Done.") } func sourceFilter(fi os.FileInfo) bool { return !strings.HasSuffix(fi.Name(), "_test.go") && !strings.HasPrefix(fi.Name(), ignoreFilePrefix1) && !strings.HasPrefix(fi.Name(), ignoreFilePrefix2) } type templateData struct { filename string Year int Package string Imports map[string]string StringFuncs map[string]bool StructFields map[string][]*structField } type structField struct { sortVal string // Lower-case version of "ReceiverType.FieldName". ReceiverVar string // The one-letter variable name to match the ReceiverType. ReceiverType string FieldName string FieldType string ZeroValue string NamedStruct bool // Getter for named struct. } func (t *templateData) processAST(f *ast.File) error { for _, decl := range f.Decls { fn, ok := decl.(*ast.FuncDecl) if ok { if fn.Recv != nil && len(fn.Recv.List) > 0 { id, ok := fn.Recv.List[0].Type.(*ast.Ident) if ok && fn.Name.Name == "String" { logf("Got FuncDecl: Name=%q, id.Name=%#v", fn.Name.Name, id.Name) t.StringFuncs[id.Name] = true } else { logf("Ignoring FuncDecl: Name=%q, Type=%T", fn.Name.Name, fn.Recv.List[0].Type) } } else { logf("Ignoring FuncDecl: Name=%q, fn=%#v", fn.Name.Name, fn) } continue } gd, ok := decl.(*ast.GenDecl) if !ok { logf("Ignoring AST decl type %T", decl) continue } for _, spec := range gd.Specs { ts, ok := spec.(*ast.TypeSpec) if !ok { continue } // Skip unexported identifiers. if !ts.Name.IsExported() { logf("Struct %v is unexported; skipping.", ts.Name) continue } // Check if the struct is blacklisted. if blacklistStruct[ts.Name.Name] { logf("Struct %v is blacklisted; skipping.", ts.Name) continue } st, ok := ts.Type.(*ast.StructType) if !ok { logf("Ignoring AST type %T, Name=%q", ts.Type, ts.Name.String()) continue } for _, field := range st.Fields.List { if len(field.Names) == 0 { continue } fieldName := field.Names[0] if id, ok := field.Type.(*ast.Ident); ok { t.addIdent(id, ts.Name.String(), fieldName.String()) continue } if _, ok := field.Type.(*ast.MapType); ok { t.addMapType(ts.Name.String(), fieldName.String()) continue } se, ok := field.Type.(*ast.StarExpr) if !ok { logf("Ignoring type %T for Name=%q, FieldName=%q", field.Type, ts.Name.String(), fieldName.String()) continue } // Skip unexported identifiers. if !fieldName.IsExported() { logf("Field %v is unexported; skipping.", fieldName) continue } // Check if "struct.method" is blacklisted. if key := fmt.Sprintf("%v.Get%v", ts.Name, fieldName); blacklistStructMethod[key] { logf("Method %v is blacklisted; skipping.", key) continue } switch x := se.X.(type) { case *ast.ArrayType: case *ast.Ident: t.addIdentPtr(x, ts.Name.String(), fieldName.String()) case *ast.MapType: case *ast.SelectorExpr: default: logf("processAST: type %q, field %q, unknown %T: %+v", ts.Name, fieldName, x, x) } } } } return nil } func (t *templateData) addMapType(receiverType, fieldName string) { t.StructFields[receiverType] = append(t.StructFields[receiverType], newStructField(receiverType, fieldName, "map[]", "nil", false)) } func (t *templateData) addIdent(x *ast.Ident, receiverType, fieldName string) { var zeroValue string var namedStruct = false switch x.String() { case "int": zeroValue = "0" case "int64": zeroValue = "0" case "float64": zeroValue = "0.0" case "string": zeroValue = `""` case "bool": zeroValue = "false" case "Timestamp": zeroValue = "Timestamp{}" default: zeroValue = "nil" namedStruct = true } t.StructFields[receiverType] = append(t.StructFields[receiverType], newStructField(receiverType, fieldName, x.String(), zeroValue, namedStruct)) } func (t *templateData) addIdentPtr(x *ast.Ident, receiverType, fieldName string) { var zeroValue string var namedStruct = false switch x.String() { case "int": zeroValue = "Int(0)" case "int64": zeroValue = "Int64(0)" case "float64": zeroValue = "Float64(0.0)" case "string": zeroValue = `String("")` case "bool": zeroValue = "Bool(false)" case "Timestamp": zeroValue = "&Timestamp{}" default: zeroValue = "nil" namedStruct = true } t.StructFields[receiverType] = append(t.StructFields[receiverType], newStructField(receiverType, fieldName, x.String(), zeroValue, namedStruct)) } func (t *templateData) dump() error { if len(t.StructFields) == 0 { logf("No StructFields for %v; skipping.", t.filename) return nil } // Remove unused structs. var toDelete []string for k := range t.StructFields { if !t.StringFuncs[k] { toDelete = append(toDelete, k) continue } } for _, k := range toDelete { delete(t.StructFields, k) } var buf bytes.Buffer if err := sourceTmpl.Execute(&buf, t); err != nil { return err } clean, err := format.Source(buf.Bytes()) if err != nil { log.Printf("failed-to-format source:\n%v", buf.String()) return err } logf("Writing %v...", t.filename) return ioutil.WriteFile(t.filename, clean, 0644) } func newStructField(receiverType, fieldName, fieldType, zeroValue string, namedStruct bool) *structField { return &structField{ sortVal: strings.ToLower(receiverType) + "." + strings.ToLower(fieldName), ReceiverVar: strings.ToLower(receiverType[:1]), ReceiverType: receiverType, FieldName: fieldName, FieldType: fieldType, ZeroValue: zeroValue, NamedStruct: namedStruct, } } func logf(fmt string, args ...interface{}) { if *verbose { log.Printf(fmt, args...) } } const source = `// Copyright {{.Year}} 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. // Code generated by gen-stringify-tests; DO NOT EDIT. package {{ $package := .Package}}{{$package}} {{with .Imports}} import ( {{- range . -}} "{{.}}" {{end -}} ) {{end}} func Float64(v float64) *float64 { return &v } {{range $key, $value := .StructFields}} func Test{{ $key }}_String(t *testing.T) { v := {{ $key }}{ {{range .}}{{if .NamedStruct}} {{ .FieldName }}: &{{ .FieldType }}{},{{else}} {{ .FieldName }}: {{.ZeroValue}},{{end}}{{end}} } want := ` + "`" + `{{ $package }}.{{ $key }}{{ $slice := . }}{ {{- range $ind, $val := .}}{{if .NamedStruct}}{{ .FieldName }}:{{ $package }}.{{ .FieldType }}{}{{else}}{{ .FieldName }}:{{ processZeroValue .ZeroValue }}{{end}}{{ isNotLast $ind $slice }}{{end}}}` + "`" + ` if got := v.String(); got != want { t.Errorf("{{ $key }}.String = %v, want %v", got, want) } } {{end}} ` go-github-28.1.1/github/gists.go000066400000000000000000000231721353501270500164400ustar00rootroot00000000000000// Copyright 2013 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "time" ) // GistsService handles communication with the Gist related // methods of the GitHub API. // // GitHub API docs: https://developer.github.com/v3/gists/ type GistsService service // Gist represents a GitHub's gist. type Gist struct { ID *string `json:"id,omitempty"` Description *string `json:"description,omitempty"` Public *bool `json:"public,omitempty"` Owner *User `json:"owner,omitempty"` Files map[GistFilename]GistFile `json:"files,omitempty"` Comments *int `json:"comments,omitempty"` HTMLURL *string `json:"html_url,omitempty"` GitPullURL *string `json:"git_pull_url,omitempty"` GitPushURL *string `json:"git_push_url,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` NodeID *string `json:"node_id,omitempty"` } func (g Gist) String() string { return Stringify(g) } // GistFilename represents filename on a gist. type GistFilename string // GistFile represents a file on a gist. type GistFile struct { Size *int `json:"size,omitempty"` Filename *string `json:"filename,omitempty"` Language *string `json:"language,omitempty"` Type *string `json:"type,omitempty"` RawURL *string `json:"raw_url,omitempty"` Content *string `json:"content,omitempty"` } func (g GistFile) String() string { return Stringify(g) } // GistCommit represents a commit on a gist. type GistCommit struct { URL *string `json:"url,omitempty"` Version *string `json:"version,omitempty"` User *User `json:"user,omitempty"` ChangeStatus *CommitStats `json:"change_status,omitempty"` CommittedAt *Timestamp `json:"committed_at,omitempty"` NodeID *string `json:"node_id,omitempty"` } func (gc GistCommit) String() string { return Stringify(gc) } // GistFork represents a fork of a gist. type GistFork struct { URL *string `json:"url,omitempty"` User *User `json:"user,omitempty"` ID *string `json:"id,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` NodeID *string `json:"node_id,omitempty"` } func (gf GistFork) String() string { return Stringify(gf) } // GistListOptions specifies the optional parameters to the // GistsService.List, GistsService.ListAll, and GistsService.ListStarred methods. type GistListOptions struct { // Since filters Gists by time. Since time.Time `url:"since,omitempty"` ListOptions } // List gists for a user. Passing the empty string will list // all public gists if called anonymously. However, if the call // is authenticated, it will returns all gists for the authenticated // user. // // GitHub API docs: https://developer.github.com/v3/gists/#list-gists func (s *GistsService) List(ctx context.Context, user string, opt *GistListOptions) ([]*Gist, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/gists", user) } else { u = "gists" } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var gists []*Gist resp, err := s.client.Do(ctx, req, &gists) if err != nil { return nil, resp, err } return gists, resp, nil } // ListAll lists all public gists. // // GitHub API docs: https://developer.github.com/v3/gists/#list-gists func (s *GistsService) ListAll(ctx context.Context, opt *GistListOptions) ([]*Gist, *Response, error) { u, err := addOptions("gists/public", opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var gists []*Gist resp, err := s.client.Do(ctx, req, &gists) if err != nil { return nil, resp, err } return gists, resp, nil } // ListStarred lists starred gists of authenticated user. // // GitHub API docs: https://developer.github.com/v3/gists/#list-gists func (s *GistsService) ListStarred(ctx context.Context, opt *GistListOptions) ([]*Gist, *Response, error) { u, err := addOptions("gists/starred", opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var gists []*Gist resp, err := s.client.Do(ctx, req, &gists) if err != nil { return nil, resp, err } return gists, resp, nil } // Get a single gist. // // GitHub API docs: https://developer.github.com/v3/gists/#get-a-single-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) if err != nil { return nil, nil, err } gist := new(Gist) resp, err := s.client.Do(ctx, req, gist) if err != nil { return nil, resp, err } return gist, resp, nil } // GetRevision gets a specific revision of a gist. // // GitHub API docs: https://developer.github.com/v3/gists/#get-a-specific-revision-of-a-gist func (s *GistsService) GetRevision(ctx context.Context, id, sha string) (*Gist, *Response, error) { u := fmt.Sprintf("gists/%v/%v", id, sha) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } gist := new(Gist) resp, err := s.client.Do(ctx, req, gist) if err != nil { return nil, resp, err } return gist, resp, nil } // Create a gist for authenticated user. // // GitHub API docs: https://developer.github.com/v3/gists/#create-a-gist func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response, error) { u := "gists" req, err := s.client.NewRequest("POST", u, gist) if err != nil { return nil, nil, err } g := new(Gist) resp, err := s.client.Do(ctx, req, g) if err != nil { return nil, resp, err } return g, resp, nil } // Edit a gist. // // GitHub API docs: https://developer.github.com/v3/gists/#edit-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) if err != nil { return nil, nil, err } g := new(Gist) resp, err := s.client.Do(ctx, req, g) if err != nil { return nil, resp, err } return g, resp, nil } // ListCommits lists commits of a gist. // // GitHub API docs: https://developer.github.com/v3/gists/#list-gist-commits func (s *GistsService) ListCommits(ctx context.Context, id string, opt *ListOptions) ([]*GistCommit, *Response, error) { u := fmt.Sprintf("gists/%v/commits", id) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var gistCommits []*GistCommit resp, err := s.client.Do(ctx, req, &gistCommits) if err != nil { return nil, resp, err } return gistCommits, resp, nil } // Delete a gist. // // GitHub API docs: https://developer.github.com/v3/gists/#delete-a-gist func (s *GistsService) Delete(ctx context.Context, id string) (*Response, error) { u := fmt.Sprintf("gists/%v", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // Star a gist on behalf of authenticated user. // // GitHub API docs: https://developer.github.com/v3/gists/#star-a-gist func (s *GistsService) Star(ctx context.Context, id string) (*Response, error) { u := fmt.Sprintf("gists/%v/star", id) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // Unstar a gist on a behalf of authenticated user. // // GitHub API docs: https://developer.github.com/v3/gists/#unstar-a-gist func (s *GistsService) Unstar(ctx context.Context, id string) (*Response, error) { u := fmt.Sprintf("gists/%v/star", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // IsStarred checks if a gist is starred by authenticated user. // // GitHub API docs: https://developer.github.com/v3/gists/#check-if-a-gist-is-starred func (s *GistsService) IsStarred(ctx context.Context, id string) (bool, *Response, error) { u := fmt.Sprintf("gists/%v/star", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } resp, err := s.client.Do(ctx, req, nil) starred, err := parseBoolResponse(err) return starred, resp, err } // Fork a gist. // // GitHub API docs: https://developer.github.com/v3/gists/#fork-a-gist func (s *GistsService) Fork(ctx context.Context, id string) (*Gist, *Response, error) { u := fmt.Sprintf("gists/%v/forks", id) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, nil, err } g := new(Gist) resp, err := s.client.Do(ctx, req, g) if err != nil { return nil, resp, err } return g, resp, nil } // ListForks lists forks of a gist. // // GitHub API docs: https://developer.github.com/v3/gists/#list-gist-forks func (s *GistsService) ListForks(ctx context.Context, id string, opt *ListOptions) ([]*GistFork, *Response, error) { u := fmt.Sprintf("gists/%v/forks", id) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var gistForks []*GistFork resp, err := s.client.Do(ctx, req, &gistForks) if err != nil { return nil, resp, err } return gistForks, resp, nil } go-github-28.1.1/github/gists_comments.go000066400000000000000000000063611353501270500203460ustar00rootroot00000000000000// 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" "time" ) // GistComment represents a Gist comment. type GistComment struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` Body *string `json:"body,omitempty"` User *User `json:"user,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` } func (g GistComment) String() string { return Stringify(g) } // ListComments lists all comments for a gist. // // GitHub API docs: https://developer.github.com/v3/gists/comments/#list-comments-on-a-gist func (s *GistsService) ListComments(ctx context.Context, gistID string, opt *ListOptions) ([]*GistComment, *Response, error) { u := fmt.Sprintf("gists/%v/comments", gistID) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var comments []*GistComment resp, err := s.client.Do(ctx, req, &comments) if err != nil { return nil, resp, err } return comments, resp, nil } // GetComment retrieves a single comment from a gist. // // GitHub API docs: https://developer.github.com/v3/gists/comments/#get-a-single-comment func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID int64) (*GistComment, *Response, error) { u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } c := new(GistComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // CreateComment creates a comment for a gist. // // GitHub API docs: https://developer.github.com/v3/gists/comments/#create-a-comment func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) { u := fmt.Sprintf("gists/%v/comments", gistID) req, err := s.client.NewRequest("POST", u, comment) if err != nil { return nil, nil, err } c := new(GistComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // EditComment edits an existing gist comment. // // GitHub API docs: https://developer.github.com/v3/gists/comments/#edit-a-comment func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) { u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) req, err := s.client.NewRequest("PATCH", u, comment) if err != nil { return nil, nil, err } c := new(GistComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // DeleteComment deletes a gist comment. // // GitHub API docs: https://developer.github.com/v3/gists/comments/#delete-a-comment func (s *GistsService) DeleteComment(ctx context.Context, gistID string, commentID int64) (*Response, error) { u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/gists_comments_test.go000066400000000000000000000130531353501270500214010ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" "time" ) func TestGistComments_marshall(t *testing.T) { testJSONMarshal(t, &GistComment{}, "{}") createdAt := time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC) u := &GistComment{ ID: Int64(1), URL: String("u"), Body: String("test gist comment"), User: &User{ Login: String("ll"), ID: Int64(123), AvatarURL: String("a"), GravatarID: String("g"), Name: String("n"), Company: String("c"), Blog: String("b"), Location: String("l"), Email: String("e"), Hireable: Bool(true), PublicRepos: Int(1), Followers: Int(1), Following: Int(1), CreatedAt: &Timestamp{referenceTime}, URL: String("u"), }, CreatedAt: &createdAt, } want := `{ "id": 1, "url": "u", "body": "test gist comment", "user": { "login": "ll", "id": 123, "avatar_url": "a", "gravatar_id": "g", "name": "n", "company": "c", "blog": "b", "location": "l", "email": "e", "hireable": true, "public_repos": 1, "followers": 1, "following": 1, "created_at": ` + referenceTimeStr + `, "url": "u" }, "created_at": "2002-02-10T15:30:00Z" }` testJSONMarshal(t, u, want) } func TestGistsService_ListComments(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/comments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id": 1}]`) }) opt := &ListOptions{Page: 2} comments, _, err := client.Gists.ListComments(context.Background(), "1", opt) if err != nil { t.Errorf("Gists.Comments returned error: %v", err) } want := []*GistComment{{ID: Int64(1)}} if !reflect.DeepEqual(comments, want) { t.Errorf("Gists.ListComments returned %+v, want %+v", comments, want) } } func TestGistsService_ListComments_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gists.ListComments(context.Background(), "%", nil) testURLParseError(t, err) } func TestGistsService_GetComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/comments/2", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id": 1}`) }) comment, _, err := client.Gists.GetComment(context.Background(), "1", 2) if err != nil { t.Errorf("Gists.GetComment returned error: %v", err) } want := &GistComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("Gists.GetComment returned %+v, want %+v", comment, want) } } func TestGistsService_GetComment_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gists.GetComment(context.Background(), "%", 1) testURLParseError(t, err) } func TestGistsService_CreateComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &GistComment{ID: Int64(1), Body: String("b")} mux.HandleFunc("/gists/1/comments", func(w http.ResponseWriter, r *http.Request) { v := new(GistComment) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) comment, _, err := client.Gists.CreateComment(context.Background(), "1", input) if err != nil { t.Errorf("Gists.CreateComment returned error: %v", err) } want := &GistComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("Gists.CreateComment returned %+v, want %+v", comment, want) } } func TestGistsService_CreateComment_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gists.CreateComment(context.Background(), "%", nil) testURLParseError(t, err) } func TestGistsService_EditComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &GistComment{ID: Int64(1), Body: String("b")} mux.HandleFunc("/gists/1/comments/2", func(w http.ResponseWriter, r *http.Request) { v := new(GistComment) 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}`) }) comment, _, err := client.Gists.EditComment(context.Background(), "1", 2, input) if err != nil { t.Errorf("Gists.EditComment returned error: %v", err) } want := &GistComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("Gists.EditComment returned %+v, want %+v", comment, want) } } func TestGistsService_EditComment_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gists.EditComment(context.Background(), "%", 1, nil) testURLParseError(t, err) } func TestGistsService_DeleteComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/comments/2", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Gists.DeleteComment(context.Background(), "1", 2) if err != nil { t.Errorf("Gists.Delete returned error: %v", err) } } func TestGistsService_DeleteComment_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Gists.DeleteComment(context.Background(), "%", 1) testURLParseError(t, err) } go-github-28.1.1/github/gists_test.go000066400000000000000000000464701353501270500175050ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" "time" ) func TestGist_marshall(t *testing.T) { testJSONMarshal(t, &Gist{}, "{}") createdAt := time.Date(2010, time.February, 10, 10, 10, 0, 0, time.UTC) updatedAt := time.Date(2010, time.February, 10, 10, 10, 0, 0, time.UTC) u := &Gist{ ID: String("i"), Description: String("description"), Public: Bool(true), Owner: &User{ Login: String("ll"), ID: Int64(123), AvatarURL: String("a"), GravatarID: String("g"), Name: String("n"), Company: String("c"), Blog: String("b"), Location: String("l"), Email: String("e"), Hireable: Bool(true), PublicRepos: Int(1), Followers: Int(1), Following: Int(1), CreatedAt: &Timestamp{referenceTime}, URL: String("u"), }, Files: map[GistFilename]GistFile{ "gistfile.py": { Size: Int(167), Filename: String("gistfile.py"), Language: String("Python"), Type: String("application/x-python"), RawURL: String("raw-url"), Content: String("c"), }, }, Comments: Int(1), HTMLURL: String("html-url"), GitPullURL: String("gitpull-url"), GitPushURL: String("gitpush-url"), CreatedAt: &createdAt, UpdatedAt: &updatedAt, NodeID: String("node"), } want := `{ "id": "i", "description": "description", "public": true, "owner": { "login": "ll", "id": 123, "avatar_url": "a", "gravatar_id": "g", "name": "n", "company": "c", "blog": "b", "location": "l", "email": "e", "hireable": true, "public_repos": 1, "followers": 1, "following": 1, "created_at": ` + referenceTimeStr + `, "url": "u" }, "files": { "gistfile.py": { "size": 167, "filename": "gistfile.py", "language": "Python", "type": "application/x-python", "raw_url": "raw-url", "content": "c" } }, "comments": 1, "html_url": "html-url", "git_pull_url": "gitpull-url", "git_push_url": "gitpush-url", "created_at": "2010-02-10T10:10:00Z", "updated_at": "2010-02-10T10:10:00Z", "node_id": "node" }` testJSONMarshal(t, u, want) } func TestGistCommit_marshall(t *testing.T) { testJSONMarshal(t, &GistCommit{}, "{}") u := &GistCommit{ URL: String("u"), Version: String("v"), User: &User{ Login: String("ll"), ID: Int64(123), AvatarURL: String("a"), GravatarID: String("g"), Name: String("n"), Company: String("c"), Blog: String("b"), Location: String("l"), Email: String("e"), Hireable: Bool(true), PublicRepos: Int(1), Followers: Int(1), Following: Int(1), CreatedAt: &Timestamp{referenceTime}, URL: String("u"), }, ChangeStatus: &CommitStats{ Additions: Int(1), Deletions: Int(1), Total: Int(2), }, CommittedAt: &Timestamp{referenceTime}, NodeID: String("node"), } want := `{ "url": "u", "version": "v", "user": { "login": "ll", "id": 123, "avatar_url": "a", "gravatar_id": "g", "name": "n", "company": "c", "blog": "b", "location": "l", "email": "e", "hireable": true, "public_repos": 1, "followers": 1, "following": 1, "created_at": ` + referenceTimeStr + `, "url": "u" }, "change_status": { "additions": 1, "deletions": 1, "total": 2 }, "committed_at": ` + referenceTimeStr + `, "node_id": "node" }` testJSONMarshal(t, u, want) } func TestGistFork_marshall(t *testing.T) { testJSONMarshal(t, &GistFork{}, "{}") u := &GistFork{ URL: String("u"), User: &User{ Login: String("ll"), ID: Int64(123), AvatarURL: String("a"), GravatarID: String("g"), Name: String("n"), Company: String("c"), Blog: String("b"), Location: String("l"), Email: String("e"), Hireable: Bool(true), PublicRepos: Int(1), Followers: Int(1), Following: Int(1), CreatedAt: &Timestamp{referenceTime}, URL: String("u"), }, ID: String("id"), CreatedAt: &Timestamp{referenceTime}, UpdatedAt: &Timestamp{referenceTime}, NodeID: String("node"), } want := `{ "url": "u", "user": { "login": "ll", "id": 123, "avatar_url": "a", "gravatar_id": "g", "name": "n", "company": "c", "blog": "b", "location": "l", "email": "e", "hireable": true, "public_repos": 1, "followers": 1, "following": 1, "created_at": ` + referenceTimeStr + `, "url": "u" }, "id": "id", "created_at": ` + referenceTimeStr + `, "updated_at": ` + referenceTimeStr + `, "node_id": "node" }` testJSONMarshal(t, u, want) } func TestGistsService_List_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() since := "2013-01-01T00:00:00Z" mux.HandleFunc("/users/u/gists", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "since": since, }) fmt.Fprint(w, `[{"id": "1"}]`) }) opt := &GistListOptions{Since: time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC)} gists, _, err := client.Gists.List(context.Background(), "u", opt) if err != nil { t.Errorf("Gists.List returned error: %v", err) } want := []*Gist{{ID: String("1")}} if !reflect.DeepEqual(gists, want) { t.Errorf("Gists.List returned %+v, want %+v", gists, want) } } func TestGistsService_List_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id": "1"}]`) }) gists, _, err := client.Gists.List(context.Background(), "", nil) if err != nil { t.Errorf("Gists.List returned error: %v", err) } want := []*Gist{{ID: String("1")}} if !reflect.DeepEqual(gists, want) { t.Errorf("Gists.List returned %+v, want %+v", gists, want) } } func TestGistsService_List_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gists.List(context.Background(), "%", nil) testURLParseError(t, err) } func TestGistsService_ListAll(t *testing.T) { client, mux, _, teardown := setup() defer teardown() since := "2013-01-01T00:00:00Z" mux.HandleFunc("/gists/public", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "since": since, }) fmt.Fprint(w, `[{"id": "1"}]`) }) opt := &GistListOptions{Since: time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC)} gists, _, err := client.Gists.ListAll(context.Background(), opt) if err != nil { t.Errorf("Gists.ListAll returned error: %v", err) } want := []*Gist{{ID: String("1")}} if !reflect.DeepEqual(gists, want) { t.Errorf("Gists.ListAll returned %+v, want %+v", gists, want) } } func TestGistsService_ListStarred(t *testing.T) { client, mux, _, teardown := setup() defer teardown() since := "2013-01-01T00:00:00Z" mux.HandleFunc("/gists/starred", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "since": since, }) fmt.Fprint(w, `[{"id": "1"}]`) }) opt := &GistListOptions{Since: time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC)} gists, _, err := client.Gists.ListStarred(context.Background(), opt) if err != nil { t.Errorf("Gists.ListStarred returned error: %v", err) } want := []*Gist{{ID: String("1")}} if !reflect.DeepEqual(gists, want) { t.Errorf("Gists.ListStarred returned %+v, want %+v", gists, want) } } func TestGistsService_Get(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id": "1"}`) }) gist, _, err := client.Gists.Get(context.Background(), "1") if err != nil { t.Errorf("Gists.Get returned error: %v", err) } want := &Gist{ID: String("1")} if !reflect.DeepEqual(gist, want) { t.Errorf("Gists.Get returned %+v, want %+v", gist, want) } } func TestGistsService_Get_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gists.Get(context.Background(), "%") testURLParseError(t, err) } func TestGistsService_GetRevision(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id": "1"}`) }) gist, _, err := client.Gists.GetRevision(context.Background(), "1", "s") if err != nil { t.Errorf("Gists.Get returned error: %v", err) } want := &Gist{ID: String("1")} if !reflect.DeepEqual(gist, want) { t.Errorf("Gists.Get returned %+v, want %+v", gist, want) } } func TestGistsService_GetRevision_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gists.GetRevision(context.Background(), "%", "%") testURLParseError(t, err) } func TestGistsService_Create(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Gist{ Description: String("Gist description"), Public: Bool(false), Files: map[GistFilename]GistFile{ "test.txt": {Content: String("Gist file content")}, }, } mux.HandleFunc("/gists", func(w http.ResponseWriter, r *http.Request) { v := new(Gist) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, ` { "id": "1", "description": "Gist description", "public": false, "files": { "test.txt": { "filename": "test.txt" } } }`) }) gist, _, err := client.Gists.Create(context.Background(), input) if err != nil { t.Errorf("Gists.Create returned error: %v", err) } want := &Gist{ ID: String("1"), Description: String("Gist description"), Public: Bool(false), Files: map[GistFilename]GistFile{ "test.txt": {Filename: String("test.txt")}, }, } if !reflect.DeepEqual(gist, want) { t.Errorf("Gists.Create returned %+v, want %+v", gist, want) } } func TestGistsService_Edit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Gist{ Description: String("New description"), Files: map[GistFilename]GistFile{ "new.txt": {Content: String("new file content")}, }, } mux.HandleFunc("/gists/1", func(w http.ResponseWriter, r *http.Request) { v := new(Gist) 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", "description": "new description", "public": false, "files": { "test.txt": { "filename": "test.txt" }, "new.txt": { "filename": "new.txt" } } }`) }) gist, _, err := client.Gists.Edit(context.Background(), "1", input) if err != nil { t.Errorf("Gists.Edit returned error: %v", err) } want := &Gist{ ID: String("1"), Description: String("new description"), Public: Bool(false), Files: map[GistFilename]GistFile{ "test.txt": {Filename: String("test.txt")}, "new.txt": {Filename: String("new.txt")}, }, } if !reflect.DeepEqual(gist, want) { t.Errorf("Gists.Edit returned %+v, want %+v", gist, want) } } func TestGistsService_Edit_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gists.Edit(context.Background(), "%", nil) testURLParseError(t, err) } func TestGistsService_ListCommits(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/commits", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, nil) fmt.Fprint(w, ` [ { "url": "https://api.github.com/gists/1/1", "version": "1", "user": { "id": 1 }, "change_status": { "deletions": 0, "additions": 180, "total": 180 }, "committed_at": "2010-01-01T00:00:00Z" } ] `) }) gistCommits, _, err := client.Gists.ListCommits(context.Background(), "1", nil) if err != nil { t.Errorf("Gists.ListCommits returned error: %v", err) } want := []*GistCommit{{ URL: String("https://api.github.com/gists/1/1"), Version: String("1"), User: &User{ID: Int64(1)}, CommittedAt: &Timestamp{time.Date(2010, time.January, 1, 00, 00, 00, 0, time.UTC)}, ChangeStatus: &CommitStats{ Additions: Int(180), Deletions: Int(0), Total: Int(180), }}} if !reflect.DeepEqual(gistCommits, want) { t.Errorf("Gists.ListCommits returned %+v, want %+v", gistCommits, want) } } func TestGistsService_ListCommits_withOptions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/commits", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[]`) }) _, _, err := client.Gists.ListCommits(context.Background(), "1", &ListOptions{Page: 2}) if err != nil { t.Errorf("Gists.ListCommits returned error: %v", err) } } func TestGistsService_ListCommits_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gists.ListCommits(context.Background(), "%", nil) testURLParseError(t, err) } func TestGistsService_Delete(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Gists.Delete(context.Background(), "1") if err != nil { t.Errorf("Gists.Delete returned error: %v", err) } } func TestGistsService_Delete_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Gists.Delete(context.Background(), "%") testURLParseError(t, err) } func TestGistsService_Star(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") }) _, err := client.Gists.Star(context.Background(), "1") if err != nil { t.Errorf("Gists.Star returned error: %v", err) } } func TestGistsService_Star_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Gists.Star(context.Background(), "%") testURLParseError(t, err) } func TestGistsService_Unstar(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Gists.Unstar(context.Background(), "1") if err != nil { t.Errorf("Gists.Unstar returned error: %v", err) } } func TestGistsService_Unstar_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Gists.Unstar(context.Background(), "%") testURLParseError(t, err) } func TestGistsService_IsStarred_hasStar(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNoContent) }) star, _, err := client.Gists.IsStarred(context.Background(), "1") if err != nil { t.Errorf("Gists.Starred returned error: %v", err) } if want := true; star != want { t.Errorf("Gists.Starred returned %+v, want %+v", star, want) } } func TestGistsService_IsStarred_noStar(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) star, _, err := client.Gists.IsStarred(context.Background(), "1") if err != nil { t.Errorf("Gists.Starred returned error: %v", err) } if want := false; star != want { t.Errorf("Gists.Starred returned %+v, want %+v", star, want) } } func TestGistsService_IsStarred_invalidID(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gists.IsStarred(context.Background(), "%") testURLParseError(t, err) } func TestGistsService_Fork(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/forks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") fmt.Fprint(w, `{"id": "2"}`) }) gist, _, err := client.Gists.Fork(context.Background(), "1") if err != nil { t.Errorf("Gists.Fork returned error: %v", err) } want := &Gist{ID: String("2")} if !reflect.DeepEqual(gist, want) { t.Errorf("Gists.Fork returned %+v, want %+v", gist, want) } } func TestGistsService_ListForks(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/forks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, nil) fmt.Fprint(w, ` [ {"url": "https://api.github.com/gists/1", "user": {"id": 1}, "id": "1", "created_at": "2010-01-01T00:00:00Z", "updated_at": "2013-01-01T00:00:00Z" } ] `) }) gistForks, _, err := client.Gists.ListForks(context.Background(), "1", nil) if err != nil { t.Errorf("Gists.ListForks returned error: %v", err) } want := []*GistFork{{ URL: String("https://api.github.com/gists/1"), ID: String("1"), User: &User{ID: Int64(1)}, CreatedAt: &Timestamp{time.Date(2010, time.January, 1, 00, 00, 00, 0, time.UTC)}, UpdatedAt: &Timestamp{time.Date(2013, time.January, 1, 00, 00, 00, 0, time.UTC)}}} if !reflect.DeepEqual(gistForks, want) { t.Errorf("Gists.ListForks returned %+v, want %+v", gistForks, want) } } func TestGistsService_ListForks_withOptions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gists/1/forks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[]`) }) gistForks, _, err := client.Gists.ListForks(context.Background(), "1", &ListOptions{Page: 2}) if err != nil { t.Errorf("Gists.ListForks returned error: %v", err) } want := []*GistFork{} if !reflect.DeepEqual(gistForks, want) { t.Errorf("Gists.ListForks returned %+v, want %+v", gistForks, want) } // Test addOptions failure _, _, err = client.Gists.ListForks(context.Background(), "%", &ListOptions{}) if err == nil { t.Error("Gists.ListForks returned err = nil") } // Test client.NewRequest failure got, resp, err := client.Gists.ListForks(context.Background(), "%", nil) if got != nil { t.Errorf("Gists.ListForks = %#v, want nil", got) } if resp != nil { t.Errorf("Gists.ListForks resp = %#v, want nil", resp) } if err == nil { t.Error("Gists.ListForks err = nil, want error") } // Test client.Do failure client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Gists.ListForks(context.Background(), "1", &ListOptions{Page: 2}) if got != nil { t.Errorf("Gists.ListForks returned = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("Gists.ListForks returned resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rGists.ListForks returned err = nil, want error") } } go-github-28.1.1/github/git.go000066400000000000000000000005521353501270500160670ustar00rootroot00000000000000// 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 // GitService handles communication with the git data related // methods of the GitHub API. // // GitHub API docs: https://developer.github.com/v3/git/ type GitService service go-github-28.1.1/github/git_blobs.go000066400000000000000000000041161353501270500172500ustar00rootroot00000000000000// 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 ( "bytes" "context" "fmt" ) // Blob represents a blob object. type Blob struct { Content *string `json:"content,omitempty"` Encoding *string `json:"encoding,omitempty"` SHA *string `json:"sha,omitempty"` Size *int `json:"size,omitempty"` URL *string `json:"url,omitempty"` NodeID *string `json:"node_id,omitempty"` } // GetBlob fetches a blob from a repo given a SHA. // // GitHub API docs: https://developer.github.com/v3/git/blobs/#get-a-blob func (s *GitService) GetBlob(ctx context.Context, owner string, repo string, sha string) (*Blob, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } blob := new(Blob) resp, err := s.client.Do(ctx, req, blob) return blob, resp, err } // GetBlobRaw fetches a blob's contents from a repo. // Unlike GetBlob, it returns the raw bytes rather than the base64-encoded data. // // GitHub API docs: https://developer.github.com/v3/git/blobs/#get-a-blob func (s *GitService) GetBlobRaw(ctx context.Context, owner, repo, sha string) ([]byte, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", "application/vnd.github.v3.raw") var buf bytes.Buffer resp, err := s.client.Do(ctx, req, &buf) return buf.Bytes(), resp, err } // CreateBlob creates a blob object. // // GitHub API docs: https://developer.github.com/v3/git/blobs/#create-a-blob func (s *GitService) CreateBlob(ctx context.Context, owner string, repo string, blob *Blob) (*Blob, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/blobs", owner, repo) req, err := s.client.NewRequest("POST", u, blob) if err != nil { return nil, nil, err } t := new(Blob) resp, err := s.client.Do(ctx, req, t) return t, resp, err } go-github-28.1.1/github/git_blobs_test.go000066400000000000000000000054431353501270500203130ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "bytes" "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestGitService_GetBlob(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/blobs/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{ "sha": "s", "content": "blob content" }`) }) blob, _, err := client.Git.GetBlob(context.Background(), "o", "r", "s") if err != nil { t.Errorf("Git.GetBlob returned error: %v", err) } want := Blob{ SHA: String("s"), Content: String("blob content"), } if !reflect.DeepEqual(*blob, want) { t.Errorf("Blob.Get returned %+v, want %+v", *blob, want) } } func TestGitService_GetBlob_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Git.GetBlob(context.Background(), "%", "%", "%") testURLParseError(t, err) } func TestGitService_GetBlobRaw(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/blobs/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", "application/vnd.github.v3.raw") fmt.Fprint(w, `raw contents here`) }) blob, _, err := client.Git.GetBlobRaw(context.Background(), "o", "r", "s") if err != nil { t.Errorf("Git.GetBlobRaw returned error: %v", err) } want := []byte("raw contents here") if !bytes.Equal(blob, want) { t.Errorf("GetBlobRaw returned %q, want %q", blob, want) } } func TestGitService_CreateBlob(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Blob{ SHA: String("s"), Content: String("blob content"), Encoding: String("utf-8"), Size: Int(12), } mux.HandleFunc("/repos/o/r/git/blobs", func(w http.ResponseWriter, r *http.Request) { v := new(Blob) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := input if !reflect.DeepEqual(v, want) { t.Errorf("Git.CreateBlob request body: %+v, want %+v", v, want) } fmt.Fprint(w, `{ "sha": "s", "content": "blob content", "encoding": "utf-8", "size": 12 }`) }) blob, _, err := client.Git.CreateBlob(context.Background(), "o", "r", input) if err != nil { t.Errorf("Git.CreateBlob returned error: %v", err) } want := input if !reflect.DeepEqual(*blob, *want) { t.Errorf("Git.CreateBlob returned %+v, want %+v", *blob, *want) } } func TestGitService_CreateBlob_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Git.CreateBlob(context.Background(), "%", "%", &Blob{}) testURLParseError(t, err) } go-github-28.1.1/github/git_commits.go000066400000000000000000000142621353501270500176250ustar00rootroot00000000000000// 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 ( "bytes" "context" "errors" "fmt" "strings" "time" "golang.org/x/crypto/openpgp" ) // SignatureVerification represents GPG signature verification. type SignatureVerification struct { Verified *bool `json:"verified,omitempty"` Reason *string `json:"reason,omitempty"` Signature *string `json:"signature,omitempty"` Payload *string `json:"payload,omitempty"` } // Commit represents a GitHub commit. type Commit struct { SHA *string `json:"sha,omitempty"` Author *CommitAuthor `json:"author,omitempty"` Committer *CommitAuthor `json:"committer,omitempty"` Message *string `json:"message,omitempty"` Tree *Tree `json:"tree,omitempty"` Parents []Commit `json:"parents,omitempty"` Stats *CommitStats `json:"stats,omitempty"` HTMLURL *string `json:"html_url,omitempty"` URL *string `json:"url,omitempty"` Verification *SignatureVerification `json:"verification,omitempty"` NodeID *string `json:"node_id,omitempty"` // CommentCount is the number of GitHub comments on the commit. This // is only populated for requests that fetch GitHub data like // Pulls.ListCommits, Repositories.ListCommits, etc. CommentCount *int `json:"comment_count,omitempty"` // SigningKey denotes a key to sign the commit with. If not nil this key will // be used to sign the commit. The private key must be present and already // decrypted. Ignored if Verification.Signature is defined. SigningKey *openpgp.Entity `json:"-"` } func (c Commit) String() string { return Stringify(c) } // CommitAuthor represents the author or committer of a commit. The commit // author may not correspond to a GitHub User. type CommitAuthor struct { Date *time.Time `json:"date,omitempty"` Name *string `json:"name,omitempty"` Email *string `json:"email,omitempty"` // The following fields are only populated by Webhook events. Login *string `json:"username,omitempty"` // Renamed for go-github consistency. } func (c CommitAuthor) String() string { return Stringify(c) } // GetCommit fetches the Commit object for a given SHA. // // GitHub API docs: https://developer.github.com/v3/git/commits/#get-a-commit func (s *GitService) GetCommit(ctx context.Context, owner string, repo string, sha string) (*Commit, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/commits/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } c := new(Commit) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // createCommit represents the body of a CreateCommit request. type createCommit struct { Author *CommitAuthor `json:"author,omitempty"` Committer *CommitAuthor `json:"committer,omitempty"` Message *string `json:"message,omitempty"` Tree *string `json:"tree,omitempty"` Parents []string `json:"parents,omitempty"` Signature *string `json:"signature,omitempty"` } // CreateCommit creates a new commit in a repository. // commit must not be nil. // // The commit.Committer is optional and will be filled with the commit.Author // data if omitted. If the commit.Author is omitted, it will be filled in with // the authenticated user’s information and the current date. // // GitHub API docs: https://developer.github.com/v3/git/commits/#create-a-commit func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string, commit *Commit) (*Commit, *Response, error) { if commit == nil { return nil, nil, fmt.Errorf("commit must be provided") } u := fmt.Sprintf("repos/%v/%v/git/commits", owner, repo) parents := make([]string, len(commit.Parents)) for i, parent := range commit.Parents { parents[i] = *parent.SHA } body := &createCommit{ Author: commit.Author, Committer: commit.Committer, Message: commit.Message, Parents: parents, } if commit.Tree != nil { body.Tree = commit.Tree.SHA } if commit.SigningKey != nil { signature, err := createSignature(commit.SigningKey, body) if err != nil { return nil, nil, err } body.Signature = &signature } if commit.Verification != nil { body.Signature = commit.Verification.Signature } req, err := s.client.NewRequest("POST", u, body) if err != nil { return nil, nil, err } c := new(Commit) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } func createSignature(signingKey *openpgp.Entity, commit *createCommit) (string, error) { if signingKey == nil || commit == nil { return "", errors.New("createSignature: invalid parameters") } message, err := createSignatureMessage(commit) if err != nil { return "", err } writer := new(bytes.Buffer) reader := bytes.NewReader([]byte(message)) if err := openpgp.ArmoredDetachSign(writer, signingKey, reader, nil); err != nil { return "", err } return writer.String(), nil } func createSignatureMessage(commit *createCommit) (string, error) { if commit == nil || commit.Message == nil || *commit.Message == "" || commit.Author == nil { return "", errors.New("createSignatureMessage: invalid parameters") } var message []string if commit.Tree != nil { message = append(message, fmt.Sprintf("tree %s", *commit.Tree)) } for _, parent := range commit.Parents { message = append(message, fmt.Sprintf("parent %s", parent)) } message = append(message, fmt.Sprintf("author %s <%s> %d %s", commit.Author.GetName(), commit.Author.GetEmail(), commit.Author.GetDate().Unix(), commit.Author.GetDate().Format("-0700"))) committer := commit.Committer if committer == nil { committer = commit.Author } // There needs to be a double newline after committer message = append(message, fmt.Sprintf("committer %s <%s> %d %s\n", committer.GetName(), committer.GetEmail(), committer.GetDate().Unix(), committer.GetDate().Format("-0700"))) message = append(message, *commit.Message) return strings.Join(message, "\n"), nil } go-github-28.1.1/github/git_commits_test.go000066400000000000000000000330511353501270500206610ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "strings" "testing" "time" "golang.org/x/crypto/openpgp" ) func TestGitService_GetCommit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/commits/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"sha":"s","message":"Commit Message.","author":{"name":"n"}}`) }) commit, _, err := client.Git.GetCommit(context.Background(), "o", "r", "s") if err != nil { t.Errorf("Git.GetCommit returned error: %v", err) } want := &Commit{SHA: String("s"), Message: String("Commit Message."), Author: &CommitAuthor{Name: String("n")}} if !reflect.DeepEqual(commit, want) { t.Errorf("Git.GetCommit returned %+v, want %+v", commit, want) } } func TestGitService_GetCommit_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Git.GetCommit(context.Background(), "%", "%", "%") testURLParseError(t, err) } func TestGitService_CreateCommit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Commit{ Message: String("Commit Message."), Tree: &Tree{SHA: String("t")}, Parents: []Commit{{SHA: String("p")}}, } mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) { v := new(createCommit) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := &createCommit{ Message: input.Message, Tree: String("t"), Parents: []string{"p"}, } if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"sha":"s"}`) }) commit, _, err := client.Git.CreateCommit(context.Background(), "o", "r", input) if err != nil { t.Errorf("Git.CreateCommit returned error: %v", err) } want := &Commit{SHA: String("s")} if !reflect.DeepEqual(commit, want) { t.Errorf("Git.CreateCommit returned %+v, want %+v", commit, want) } } func TestGitService_CreateSignedCommit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() signature := "----- BEGIN PGP SIGNATURE -----\n\naaaa\naaaa\n----- END PGP SIGNATURE -----" input := &Commit{ Message: String("Commit Message."), Tree: &Tree{SHA: String("t")}, Parents: []Commit{{SHA: String("p")}}, Verification: &SignatureVerification{ Signature: String(signature), }, } mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) { v := new(createCommit) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := &createCommit{ Message: input.Message, Tree: String("t"), Parents: []string{"p"}, Signature: String(signature), } if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"sha":"commitSha"}`) }) commit, _, err := client.Git.CreateCommit(context.Background(), "o", "r", input) if err != nil { t.Errorf("Git.CreateCommit returned error: %v", err) } want := &Commit{SHA: String("commitSha")} if !reflect.DeepEqual(commit, want) { t.Errorf("Git.CreateCommit returned %+v, want %+v", commit, want) } } func TestGitService_CreateSignedCommitWithInvalidParams(t *testing.T) { client, _, _, teardown := setup() defer teardown() input := &Commit{ SigningKey: &openpgp.Entity{}, } _, _, err := client.Git.CreateCommit(context.Background(), "o", "r", input) if err == nil { t.Errorf("Expected error to be returned because invalid params was passed") } } func TestGitService_CreateSignedCommitWithKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() s := strings.NewReader(testGPGKey) keyring, err := openpgp.ReadArmoredKeyRing(s) if err != nil { t.Errorf("Error reading keyring: %+v", err) } date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") author := CommitAuthor{ Name: String("go-github"), Email: String("go-github@github.com"), Date: &date, } input := &Commit{ Message: String("Commit Message."), Tree: &Tree{SHA: String("t")}, Parents: []Commit{{SHA: String("p")}}, SigningKey: keyring[0], Author: &author, } messageReader := strings.NewReader(`tree t parent p author go-github 1493849023 +0200 committer go-github 1493849023 +0200 Commit Message.`) mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) { v := new(createCommit) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := &createCommit{ Message: input.Message, Tree: String("t"), Parents: []string{"p"}, Author: &author, } sigReader := strings.NewReader(*v.Signature) signer, err := openpgp.CheckArmoredDetachedSignature(keyring, messageReader, sigReader) if err != nil { t.Errorf("Error verifying signature: %+v", err) } if signer.Identities["go-github "].Name != "go-github " { t.Errorf("Signer is incorrect. got: %+v, want %+v", signer.Identities["go-github "].Name, "go-github ") } // Nullify Signature since we checked it above v.Signature = nil if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"sha":"commitSha"}`) }) commit, _, err := client.Git.CreateCommit(context.Background(), "o", "r", input) if err != nil { t.Errorf("Git.CreateCommit returned error: %v", err) } want := &Commit{SHA: String("commitSha")} if !reflect.DeepEqual(commit, want) { t.Errorf("Git.CreateCommit returned %+v, want %+v", commit, want) } } func TestGitService_createSignature_nilSigningKey(t *testing.T) { a := &createCommit{ Message: String("Commit Message."), Tree: String("t"), Parents: []string{"p"}, } _, err := createSignature(nil, a) if err == nil { t.Errorf("Expected error to be returned because no author was passed") } } func TestGitService_createSignature_nilCommit(t *testing.T) { _, err := createSignature(&openpgp.Entity{}, nil) if err == nil { t.Errorf("Expected error to be returned because no author was passed") } } func TestGitService_createSignature_noAuthor(t *testing.T) { a := &createCommit{ Message: String("Commit Message."), Tree: String("t"), Parents: []string{"p"}, } _, err := createSignature(&openpgp.Entity{}, a) if err == nil { t.Errorf("Expected error to be returned because no author was passed") } } func TestGitService_createSignature_invalidKey(t *testing.T) { date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") _, err := createSignature(&openpgp.Entity{}, &createCommit{ Message: String("Commit Message."), Tree: String("t"), Parents: []string{"p"}, Author: &CommitAuthor{ Name: String("go-github"), Email: String("go-github@github.com"), Date: &date, }, }) if err == nil { t.Errorf("Expected error to be returned due to invalid key") } } func TestGitService_createSignatureMessage_nilCommit(t *testing.T) { _, err := createSignatureMessage(nil) if err == nil { t.Errorf("Expected error to be returned due to nil key") } } func TestGitService_createSignatureMessage_nilMessage(t *testing.T) { date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") _, err := createSignatureMessage(&createCommit{ Message: nil, Parents: []string{"p"}, Author: &CommitAuthor{ Name: String("go-github"), Email: String("go-github@github.com"), Date: &date, }, }) if err == nil { t.Errorf("Expected error to be returned due to nil key") } } func TestGitService_createSignatureMessage_emptyMessage(t *testing.T) { date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") emptyString := "" _, err := createSignatureMessage(&createCommit{ Message: &emptyString, Parents: []string{"p"}, Author: &CommitAuthor{ Name: String("go-github"), Email: String("go-github@github.com"), Date: &date, }, }) if err == nil { t.Errorf("Expected error to be returned due to nil key") } } func TestGitService_createSignatureMessage_nilAuthor(t *testing.T) { _, err := createSignatureMessage(&createCommit{ Message: String("Commit Message."), Parents: []string{"p"}, Author: nil, }) if err == nil { t.Errorf("Expected error to be returned due to nil key") } } func TestGitService_createSignatureMessage_withoutTree(t *testing.T) { date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") msg, _ := createSignatureMessage(&createCommit{ Message: String("Commit Message."), Parents: []string{"p"}, Author: &CommitAuthor{ Name: String("go-github"), Email: String("go-github@github.com"), Date: &date, }, }) expected := `parent p author go-github 1493849023 +0200 committer go-github 1493849023 +0200 Commit Message.` if msg != expected { t.Errorf("Returned message incorrect. returned %s, want %s", msg, expected) } } func TestGitService_createSignatureMessage_withoutCommitter(t *testing.T) { date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") msg, _ := createSignatureMessage(&createCommit{ Message: String("Commit Message."), Parents: []string{"p"}, Author: &CommitAuthor{ Name: String("go-github"), Email: String("go-github@github.com"), Date: &date, }, Committer: &CommitAuthor{ Name: String("foo"), Email: String("foo@bar.com"), Date: &date, }, }) expected := `parent p author go-github 1493849023 +0200 committer foo 1493849023 +0200 Commit Message.` if msg != expected { t.Errorf("Returned message incorrect. returned %s, want %s", msg, expected) } } func TestGitService_CreateCommit_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Git.CreateCommit(context.Background(), "%", "%", &Commit{}) testURLParseError(t, err) } const testGPGKey = ` -----BEGIN PGP PRIVATE KEY BLOCK----- lQOYBFyi1qYBCAD3EPfLJzIt4qkAceUKkhdvfaIvOsBwXbfr5sSu/lkMqL0Wq47+ iv+SRwOC7zvN8SlB8nPUgs5dbTRCJJfG5MAqTRR7KZRbyq2jBpi4BtmO30Ul/qId 3A18cVUfgVbxH85K9bdnyOxep/Q2NjLjTKmWLkzgmgkfbUmSLuWW9HRXPjYy9B7i dOFD6GdkN/HwPAaId8ym0TE1mIuSpw8UQHyxusAkK52Pn4h/PgJhLTzbSi1X2eDt OgzjhbdxTPzKFQfs97dY8y9C7Bt+CqH6Bvr3785LeKdxiUnCjfUJ+WAoJy780ec+ IVwSpPp1CaEtzu73w6GH5945GELHE8HRe25FABEBAAEAB/9dtx72/VAoXZCTbaBe iRnAnZwWZCe4t6PbJHa4lhv7FEpdPggIf3r/5lXrpYk+zdpDfI75LgDPKWwoJq83 r29A3GoHabcvtkp0yzzEmTyO2BvnlJWz09N9v5N1Vt8+qTzb7CZ8hJc8NGMK6TYW R+8P21In4+XP+OluPMGzp9g1etHScLhQUtF/xcN3JQGkeq4CPX6jUSYlJNeEtuLm xjBTLBdg8zK5mJ3tolvnS/VhSTdiBeUaYtVt/qxq+fPqdFGHrO5H9ORbt56ahU+f Ne86sOjQfJZPsx9z8ffP+XhLZPT1ZUGJMI/Vysx9gwDiEnaxrCJ02fO0Dnqsj/o2 T14lBAD55+KtaS0C0OpHpA/F+XhL3IDcYQOYgu8idBTshr4vv7M+jdZqpECOn72Q 8SZJ+gYMcA9Z07Afnin1DVdtxiMN/tbyOu7e1BE7y77eA+zQw4PjLJPZJMbco7z+ q9ZnZF3GyRyil6HkKUTfrao8AMtb0allZnqXwpPb5Mza32VqtwQA/RdbG6OIS6og OpP7zKu4GP4guBk8NrVpVuV5Xz4r8JlL+POt0TadlT93coW/SajLrN/eeUwk6jQw wrabmIGMarG5mrC4tnXLze5LICJTpOuqCACyFwL6w/ag+c7Qt9t9hvLMDFifcZW/ mylqY7Z1eVcnbOcFsQG+0LzJBU0qouMEAKkXmJcQ3lJM8yoJuYOvbwexVR+5Y+5v FNEGPlp3H/fq6ETYWHjMxPOE5dvGbQL8oKWZgkkHEGAKAavEGebM/y/qIPOCAluT tn1sfx//n6kTMhswpg/3+BciUaJFjwYbIwUH5XD0vFbe9O2VOfTVdo1p19wegVs5 LMf8rWFWYXtqUgG0IGdvLWdpdGh1YiA8Z28tZ2l0aHViQGdpdGh1Yi5jb20+iQFU BBMBCAA+FiEELZ6AMqOpBMVblK0uiKTQXVy+MAsFAlyi1qYCGwMFCQPCZwAFCwkI BwIGFQoJCAsCBBYCAwECHgECF4AACgkQiKTQXVy+MAtEYggA0LRecz71HUjEKXJj C5Wgds1hZ0q+g3ew7zms4fuascd/2PqT5lItHU3oezdzMOHetSPvPzJILjl7RYcY pWvoyzEBC5MutlmuzfwUa7qYCiuRDkYRjke8a4o8ijsxc8ANXwulXcI3udjAZdV0 CKjrjPTyrHFUnPyZyaZp8p2eX62iPYhaXkoBnEiarf0xKtJuT/8IlP5n/redlKYz GIHG5Svg3uDq9E09BOjFsgemhPyqbf7yrh5aRwDOIdHtn9mNevFPfQ1jO8lI/wbe 4kC6zXM7te0/ZkM06DYRhcaeoYdeyY/gvE+w7wU/+f7Wzqt+LxOMIjKk0oDxZIv9 praEM50DmARcotamAQgAsiO75WZvjt7BEAzdTvWekWXqBo4NOes2UgzSYToVs6xW 8iXnE+mpDS7GHtNQLU6oeC0vizUjCwBfU+qGqw1JjI3I1pwv7xRqBIlA6f5ancVK KiMx+/HxasbBrbav8DmZT8E8VaJhYM614Kav91W8YoqK5YXmP/A+OwwhkVEGo8v3 Iy7mnJPMSjNiNTpiDgc5wvRiTan+uf+AtNPUS0k0fbrTZWosbrSmBymhrEy8stMj rG2wZX5aRY7AXrQXoIXedqvP3kW/nqd0wvuiD11ZZWvoawjZRRVsT27DED0x2+o6 aAEKrSLj8LlWvGVkD/jP9lSkC81uwGgD5VIMeXv6EQARAQABAAf7BHef8SdJ+ee9 KLVh4WaIdPX80fBDBaZP5OvcZMLLo4dZYNYxfs7XxfRb1I8RDinQUL81V4TcHZ0D Rvv1J5n8M7GkjTk6fIDjDb0RayzNQfKeIwNh8AMHvllApyYTMG+JWDYs2KrrTT2x 0vHrLMUyJbh6tjnO5eCU9u8dcmL5Syc6DzGUvDl6ZdJxlHEEJOwMlVCwQn5LQDVI t0KEXigqs7eDCpTduJeAI7oA96s/8LwdlG5t6q9vbkEjl1XpR5FfKvJcZbd7Kmk9 6R0EdbH6Ffe8qAp8lGmjx+91gqeL7jyl500H4gK/ybzlxQczIsbQ7WcZTPEnROIX tCFWh6puvwQAyV6ygcatz+1BfCfgxWNYFXyowwOGSP9Nma+/aDVdeRCjZ69Is0lz GV0NNqh7hpaoVbXS9Vc3sFOwBr5ZyKQaf07BoCDW+XJtvPyyZNLb004smtB5uHCf uWDBpQ9erlrpSkOLgifbzfkYHdSvhc2ws9Tgab7Mk7P/ExOZjnUJPOcEAOJ3q/2/ 0wqRnkSelgkWwUmZ+hFIBz6lgWS3KTJs6Qc5WBnXono+EOoqhFxsiRM4lewExxHM kPIcxb+0hiNz8hJkWOHEdgkXNim9Q08J0HPz6owtlD/rtmOi2+7d5BukbY/3JEXs r2bjqbXXIE7heytIn/dQv7aEDyDqexiJKnpHBACQItjuYlewLt94NMNdGcwxmKdJ bfaoIQz1h8fX5uSGKU+hXatI6sltD9PrhwwhdqJNcQ0K1dRkm24olO4I/sJwactI G3r1UTq6BMV94eIyS/zZH5xChlOUavy9PrgU3kAK21bdmAFuNwbHnN34BBUk9J6f IIxEZUOxw2CrKhsubUOuiQE8BBgBCAAmFiEELZ6AMqOpBMVblK0uiKTQXVy+MAsF Alyi1qYCGwwFCQPCZwAACgkQiKTQXVy+MAstJAf/Tm2hfagVjzgJ5pFHmpP+fYxp 8dIPZLonP5HW12iaSOXThtvWBY578Cb9RmU+WkHyPXg8SyshW7aco4HrUDk+Qmyi f9BvHS5RsLbyPlhgCqNkn+3QS62fZiIlbHLrQ/6iHXkgLV04Fnj+F4v8YYpOI9nY NFc5iWm0zZRcLiRKZk1up8SCngyolcjVuTuCXDKyAUX1jRqDu7tlN0qVH0CYDGch BqTKXNkzAvV+CKOyaUILSBBWdef+cxVrDCJuuC3894x3G1FjJycOy0m9PArvGtSG g7/0Bp9oLXwiHzFoUMDvx+WlPnPHQNcufmQXUNdZvg+Ad4/unEU81EGDBDz3Eg== =VFSn -----END PGP PRIVATE KEY BLOCK-----` go-github-28.1.1/github/git_refs.go000066400000000000000000000152431353501270500171110ustar00rootroot00000000000000// 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" "encoding/json" "errors" "fmt" "net/url" "strings" ) // Reference represents a GitHub reference. type Reference struct { Ref *string `json:"ref"` URL *string `json:"url"` Object *GitObject `json:"object"` NodeID *string `json:"node_id,omitempty"` } func (r Reference) String() string { return Stringify(r) } // GitObject represents a Git object. type GitObject struct { Type *string `json:"type"` SHA *string `json:"sha"` URL *string `json:"url"` } func (o GitObject) String() string { return Stringify(o) } // createRefRequest represents the payload for creating a reference. type createRefRequest struct { Ref *string `json:"ref"` SHA *string `json:"sha"` } // updateRefRequest represents the payload for updating a reference. type updateRefRequest struct { SHA *string `json:"sha"` Force *bool `json:"force"` } // GetRef fetches a single Reference object for a given Git ref. // If there is no exact match, GetRef will return an error. // // Note: The GitHub API can return multiple matches. // If you wish to use this functionality please use the GetRefs() method. // // GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference 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, url.QueryEscape(ref)) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } r := new(Reference) resp, err := s.client.Do(ctx, req, r) if _, ok := err.(*json.UnmarshalTypeError); ok { // Multiple refs, means there wasn't an exact match. return nil, resp, errors.New("multiple matches found for this ref") } else if _, ok := err.(*ErrorResponse); ok && resp.StatusCode == 404 { // No ref, there was no match for the ref return nil, resp, errors.New("no match found for this ref") } else if err != nil { return nil, resp, err } return r, resp, nil } // GetRefs fetches a slice of Reference objects for a given Git ref. // If there is an exact match, only that ref is returned. // If there is no exact match, GitHub returns all refs that start with ref. // If returned error is nil, there will be at least 1 ref returned. // For example: // // "heads/featureA" -> ["refs/heads/featureA"] // Exact match, single ref is returned. // "heads/feature" -> ["refs/heads/featureA", "refs/heads/featureB"] // All refs that start with ref. // "heads/notexist" -> [] // Returns an error. // // GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference func (s *GitService) GetRefs(ctx context.Context, owner string, repo string, ref string) ([]*Reference, *Response, error) { ref = strings.TrimPrefix(ref, "refs/") u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, url.QueryEscape(ref)) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var rawJSON json.RawMessage resp, err := s.client.Do(ctx, req, &rawJSON) if err != nil { return nil, resp, err } // Prioritize the most common case: a single returned ref. r := new(Reference) singleUnmarshalError := json.Unmarshal(rawJSON, r) if singleUnmarshalError == nil { return []*Reference{r}, resp, nil } // Attempt to unmarshal multiple refs. var rs []*Reference multipleUnmarshalError := json.Unmarshal(rawJSON, &rs) if multipleUnmarshalError == nil { if len(rs) == 0 { return nil, resp, fmt.Errorf("unexpected response from GitHub API: an array of refs with length 0") } return rs, resp, nil } return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", singleUnmarshalError, multipleUnmarshalError) } // ReferenceListOptions specifies optional parameters to the // GitService.ListRefs method. type ReferenceListOptions struct { Type string `url:"-"` ListOptions } // ListRefs lists all refs in a repository. // // GitHub API docs: https://developer.github.com/v3/git/refs/#get-all-references func (s *GitService) ListRefs(ctx context.Context, owner, repo string, opt *ReferenceListOptions) ([]*Reference, *Response, error) { var u string if opt != nil && opt.Type != "" { u = fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, opt.Type) } else { u = fmt.Sprintf("repos/%v/%v/git/refs", owner, repo) } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var rs []*Reference resp, err := s.client.Do(ctx, req, &rs) if err != nil { return nil, resp, err } return rs, resp, nil } // CreateRef creates a new ref in a repository. // // GitHub API docs: https://developer.github.com/v3/git/refs/#create-a-reference func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, ref *Reference) (*Reference, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/refs", owner, repo) req, err := s.client.NewRequest("POST", u, &createRefRequest{ // back-compat with previous behavior that didn't require 'refs/' prefix Ref: String("refs/" + strings.TrimPrefix(*ref.Ref, "refs/")), SHA: ref.Object.SHA, }) if err != nil { return nil, nil, err } r := new(Reference) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // UpdateRef updates an existing ref in a repository. // // GitHub API docs: https://developer.github.com/v3/git/refs/#update-a-reference func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) { refPath := strings.TrimPrefix(*ref.Ref, "refs/") u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refPath) req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{ SHA: ref.Object.SHA, Force: &force, }) if err != nil { return nil, nil, err } r := new(Reference) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // DeleteRef deletes a ref from a repository. // // GitHub API docs: https://developer.github.com/v3/git/refs/#delete-a-reference func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) { ref = strings.TrimPrefix(ref, "refs/") u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, url.QueryEscape(ref)) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/git_refs_test.go000066400000000000000000000326351353501270500201540ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestGitService_GetRef_singleRef(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, ` { "ref": "refs/heads/b", "url": "https://api.github.com/repos/o/r/git/refs/heads/b", "object": { "type": "commit", "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd", "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd" } }`) }) ref, _, err := client.Git.GetRef(context.Background(), "o", "r", "refs/heads/b") if err != nil { t.Fatalf("Git.GetRef returned error: %v", err) } want := &Reference{ Ref: String("refs/heads/b"), URL: String("https://api.github.com/repos/o/r/git/refs/heads/b"), Object: &GitObject{ Type: String("commit"), SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"), }, } if !reflect.DeepEqual(ref, want) { t.Errorf("Git.GetRef returned %+v, want %+v", ref, want) } // without 'refs/' prefix if _, _, err := client.Git.GetRef(context.Background(), "o", "r", "heads/b"); err != nil { t.Errorf("Git.GetRef returned error: %v", err) } } func TestGitService_GetRef_noRefs(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) fmt.Fprint(w, "[]") }) _, _, err := client.Git.GetRef(context.Background(), "o", "r", "refs/heads/b") want := "no match found for this ref" if err.Error() != want { t.Errorf("Git.GetRef returned %+v, want %+v", err, want) } } func TestGitService_GetRef_multipleRefs(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, ` [ { "ref": "refs/heads/booger", "url": "https://api.github.com/repos/o/r/git/refs/heads/booger", "object": { "type": "commit", "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd", "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd" } }, { "ref": "refs/heads/bandsaw", "url": "https://api.github.com/repos/o/r/git/refs/heads/bandsaw", "object": { "type": "commit", "sha": "612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac", "url": "https://api.github.com/repos/o/r/git/commits/612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac" } } ] `) }) _, _, err := client.Git.GetRef(context.Background(), "o", "r", "refs/heads/b") want := "multiple matches found for this ref" if err.Error() != want { t.Errorf("Git.GetRef returned %+v, want %+v", err, want) } } func TestGitService_GetRefs_singleRef(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, ` { "ref": "refs/heads/b", "url": "https://api.github.com/repos/o/r/git/refs/heads/b", "object": { "type": "commit", "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd", "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd" } }`) }) refs, _, err := client.Git.GetRefs(context.Background(), "o", "r", "refs/heads/b") if err != nil { t.Fatalf("Git.GetRefs returned error: %v", err) } ref := refs[0] want := &Reference{ Ref: String("refs/heads/b"), URL: String("https://api.github.com/repos/o/r/git/refs/heads/b"), Object: &GitObject{ Type: String("commit"), SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"), }, } if !reflect.DeepEqual(ref, want) { t.Errorf("Git.GetRefs returned %+v, want %+v", ref, want) } // without 'refs/' prefix if _, _, err := client.Git.GetRefs(context.Background(), "o", "r", "heads/b"); err != nil { t.Errorf("Git.GetRefs returned error: %v", err) } } func TestGitService_GetRefs_multipleRefs(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, ` [ { "ref": "refs/heads/booger", "url": "https://api.github.com/repos/o/r/git/refs/heads/booger", "object": { "type": "commit", "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd", "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd" } }, { "ref": "refs/heads/bandsaw", "url": "https://api.github.com/repos/o/r/git/refs/heads/bandsaw", "object": { "type": "commit", "sha": "612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac", "url": "https://api.github.com/repos/o/r/git/commits/612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac" } } ] `) }) refs, _, err := client.Git.GetRefs(context.Background(), "o", "r", "refs/heads/b") if err != nil { t.Errorf("Git.GetRefs returned error: %v", err) } want := &Reference{ Ref: String("refs/heads/booger"), URL: String("https://api.github.com/repos/o/r/git/refs/heads/booger"), Object: &GitObject{ Type: String("commit"), SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"), }, } if !reflect.DeepEqual(refs[0], want) { t.Errorf("Git.GetRefs returned %+v, want %+v", refs[0], want) } } // TestGitService_GetRefs_noRefs tests for behaviour resulting from an unexpected GH response. This should never actually happen. func TestGitService_GetRefs_noRefs(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, "[]") }) _, _, err := client.Git.GetRefs(context.Background(), "o", "r", "refs/heads/b") want := "unexpected response from GitHub API: an array of refs with length 0" if err.Error() != want { t.Errorf("Git.GetRefs returned %+v, want %+v", err, want) } } func TestGitService_ListRefs(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/refs", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, ` [ { "ref": "refs/heads/branchA", "url": "https://api.github.com/repos/o/r/git/refs/heads/branchA", "object": { "type": "commit", "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd", "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd" } }, { "ref": "refs/heads/branchB", "url": "https://api.github.com/repos/o/r/git/refs/heads/branchB", "object": { "type": "commit", "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd", "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd" } } ]`) }) refs, _, err := client.Git.ListRefs(context.Background(), "o", "r", nil) if err != nil { t.Errorf("Git.ListRefs returned error: %v", err) } want := []*Reference{ { Ref: String("refs/heads/branchA"), URL: String("https://api.github.com/repos/o/r/git/refs/heads/branchA"), Object: &GitObject{ Type: String("commit"), SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"), }, }, { Ref: String("refs/heads/branchB"), URL: String("https://api.github.com/repos/o/r/git/refs/heads/branchB"), Object: &GitObject{ Type: String("commit"), SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"), }, }, } if !reflect.DeepEqual(refs, want) { t.Errorf("Git.ListRefs returned %+v, want %+v", refs, want) } } func TestGitService_ListRefs_options(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/refs/t", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"ref": "r"}]`) }) opt := &ReferenceListOptions{Type: "t", ListOptions: ListOptions{Page: 2}} refs, _, err := client.Git.ListRefs(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Git.ListRefs returned error: %v", err) } want := []*Reference{{Ref: String("r")}} if !reflect.DeepEqual(refs, want) { t.Errorf("Git.ListRefs returned %+v, want %+v", refs, want) } } func TestGitService_CreateRef(t *testing.T) { client, mux, _, teardown := setup() defer teardown() args := &createRefRequest{ Ref: String("refs/heads/b"), SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), } mux.HandleFunc("/repos/o/r/git/refs", func(w http.ResponseWriter, r *http.Request) { v := new(createRefRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, args) { t.Errorf("Request body = %+v, want %+v", v, args) } fmt.Fprint(w, ` { "ref": "refs/heads/b", "url": "https://api.github.com/repos/o/r/git/refs/heads/b", "object": { "type": "commit", "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd", "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd" } }`) }) ref, _, err := client.Git.CreateRef(context.Background(), "o", "r", &Reference{ Ref: String("refs/heads/b"), Object: &GitObject{ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), }, }) if err != nil { t.Errorf("Git.CreateRef returned error: %v", err) } want := &Reference{ Ref: String("refs/heads/b"), URL: String("https://api.github.com/repos/o/r/git/refs/heads/b"), Object: &GitObject{ Type: String("commit"), SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"), }, } if !reflect.DeepEqual(ref, want) { t.Errorf("Git.CreateRef returned %+v, want %+v", ref, want) } // without 'refs/' prefix _, _, err = client.Git.CreateRef(context.Background(), "o", "r", &Reference{ Ref: String("heads/b"), Object: &GitObject{ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), }, }) if err != nil { t.Errorf("Git.CreateRef returned error: %v", err) } } func TestGitService_UpdateRef(t *testing.T) { client, mux, _, teardown := setup() defer teardown() args := &updateRefRequest{ SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), Force: Bool(true), } mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) { v := new(updateRefRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") if !reflect.DeepEqual(v, args) { t.Errorf("Request body = %+v, want %+v", v, args) } fmt.Fprint(w, ` { "ref": "refs/heads/b", "url": "https://api.github.com/repos/o/r/git/refs/heads/b", "object": { "type": "commit", "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd", "url": "https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd" } }`) }) ref, _, err := client.Git.UpdateRef(context.Background(), "o", "r", &Reference{ Ref: String("refs/heads/b"), Object: &GitObject{SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd")}, }, true) if err != nil { t.Errorf("Git.UpdateRef returned error: %v", err) } want := &Reference{ Ref: String("refs/heads/b"), URL: String("https://api.github.com/repos/o/r/git/refs/heads/b"), Object: &GitObject{ Type: String("commit"), SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd"), URL: String("https://api.github.com/repos/o/r/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"), }, } if !reflect.DeepEqual(ref, want) { t.Errorf("Git.UpdateRef returned %+v, want %+v", ref, want) } // without 'refs/' prefix _, _, err = client.Git.UpdateRef(context.Background(), "o", "r", &Reference{ Ref: String("heads/b"), Object: &GitObject{SHA: String("aa218f56b14c9653891f9e74264a383fa43fefbd")}, }, true) if err != nil { t.Errorf("Git.UpdateRef returned error: %v", err) } } func TestGitService_DeleteRef(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/refs/heads/b", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Git.DeleteRef(context.Background(), "o", "r", "refs/heads/b") if err != nil { t.Errorf("Git.DeleteRef returned error: %v", err) } // without 'refs/' prefix if _, err := client.Git.DeleteRef(context.Background(), "o", "r", "heads/b"); err != nil { t.Errorf("Git.DeleteRef returned error: %v", err) } } go-github-28.1.1/github/git_tags.go000066400000000000000000000046321353501270500171100ustar00rootroot00000000000000// 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" ) // Tag represents a tag object. type Tag struct { Tag *string `json:"tag,omitempty"` SHA *string `json:"sha,omitempty"` URL *string `json:"url,omitempty"` Message *string `json:"message,omitempty"` Tagger *CommitAuthor `json:"tagger,omitempty"` Object *GitObject `json:"object,omitempty"` Verification *SignatureVerification `json:"verification,omitempty"` NodeID *string `json:"node_id,omitempty"` } // createTagRequest represents the body of a CreateTag request. This is mostly // identical to Tag with the exception that the object SHA and Type are // top-level fields, rather than being nested inside a JSON object. type createTagRequest struct { Tag *string `json:"tag,omitempty"` Message *string `json:"message,omitempty"` Object *string `json:"object,omitempty"` Type *string `json:"type,omitempty"` Tagger *CommitAuthor `json:"tagger,omitempty"` } // GetTag fetches a tag from a repo given a SHA. // // GitHub API docs: https://developer.github.com/v3/git/tags/#get-a-tag func (s *GitService) GetTag(ctx context.Context, owner string, repo string, sha string) (*Tag, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/tags/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } tag := new(Tag) resp, err := s.client.Do(ctx, req, tag) return tag, resp, err } // CreateTag creates a tag object. // // GitHub API docs: https://developer.github.com/v3/git/tags/#create-a-tag-object func (s *GitService) CreateTag(ctx context.Context, owner string, repo string, tag *Tag) (*Tag, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/tags", owner, repo) // convert Tag into a createTagRequest tagRequest := &createTagRequest{ Tag: tag.Tag, Message: tag.Message, Tagger: tag.Tagger, } if tag.Object != nil { tagRequest.Object = tag.Object.SHA tagRequest.Type = tag.Object.Type } req, err := s.client.NewRequest("POST", u, tagRequest) if err != nil { return nil, nil, err } t := new(Tag) resp, err := s.client.Do(ctx, req, t) return t, resp, err } go-github-28.1.1/github/git_tags_test.go000066400000000000000000000031221353501270500201400ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestGitService_GetTag(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/tags/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"tag": "t"}`) }) tag, _, err := client.Git.GetTag(context.Background(), "o", "r", "s") if err != nil { t.Errorf("Git.GetTag returned error: %v", err) } want := &Tag{Tag: String("t")} if !reflect.DeepEqual(tag, want) { t.Errorf("Git.GetTag returned %+v, want %+v", tag, want) } } func TestGitService_CreateTag(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &createTagRequest{Tag: String("t"), Object: String("s")} mux.HandleFunc("/repos/o/r/git/tags", func(w http.ResponseWriter, r *http.Request) { v := new(createTagRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"tag": "t"}`) }) tag, _, err := client.Git.CreateTag(context.Background(), "o", "r", &Tag{ Tag: input.Tag, Object: &GitObject{SHA: input.Object}, }) if err != nil { t.Errorf("Git.CreateTag returned error: %v", err) } want := &Tag{Tag: String("t")} if !reflect.DeepEqual(tag, want) { t.Errorf("Git.GetTag returned %+v, want %+v", tag, want) } } go-github-28.1.1/github/git_trees.go000066400000000000000000000053351353501270500172750ustar00rootroot00000000000000// 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" ) // Tree represents a GitHub tree. type Tree struct { SHA *string `json:"sha,omitempty"` Entries []TreeEntry `json:"tree,omitempty"` // Truncated is true if the number of items in the tree // exceeded GitHub's maximum limit and the Entries were truncated // in the response. Only populated for requests that fetch // trees like Git.GetTree. Truncated *bool `json:"truncated,omitempty"` } func (t Tree) String() string { return Stringify(t) } // TreeEntry represents the contents of a tree structure. TreeEntry can // represent either a blob, a commit (in the case of a submodule), or another // tree. type TreeEntry struct { SHA *string `json:"sha,omitempty"` Path *string `json:"path,omitempty"` Mode *string `json:"mode,omitempty"` Type *string `json:"type,omitempty"` Size *int `json:"size,omitempty"` Content *string `json:"content,omitempty"` URL *string `json:"url,omitempty"` } func (t TreeEntry) String() string { return Stringify(t) } // GetTree fetches the Tree object for a given sha hash from a repository. // // GitHub API docs: https://developer.github.com/v3/git/trees/#get-a-tree func (s *GitService) GetTree(ctx context.Context, owner string, repo string, sha string, recursive bool) (*Tree, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/trees/%v", owner, repo, sha) if recursive { u += "?recursive=1" } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } t := new(Tree) resp, err := s.client.Do(ctx, req, t) if err != nil { return nil, resp, err } return t, resp, nil } // createTree represents the body of a CreateTree request. type createTree struct { BaseTree string `json:"base_tree,omitempty"` Entries []TreeEntry `json:"tree"` } // CreateTree creates a new tree in a repository. If both a tree and a nested // path modifying that tree are specified, it will overwrite the contents of // that tree with the new path contents and write a new tree out. // // GitHub API docs: https://developer.github.com/v3/git/trees/#create-a-tree func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []TreeEntry) (*Tree, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo) body := &createTree{ BaseTree: baseTree, Entries: entries, } req, err := s.client.NewRequest("POST", u, body) if err != nil { return nil, nil, err } t := new(Tree) resp, err := s.client.Do(ctx, req, t) if err != nil { return nil, resp, err } return t, resp, nil } go-github-28.1.1/github/git_trees_test.go000066400000000000000000000107211353501270500203270ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestGitService_GetTree(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/git/trees/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{ "sha": "s", "tree": [ { "type": "blob" } ], "truncated": true }`) }) tree, _, err := client.Git.GetTree(context.Background(), "o", "r", "s", true) if err != nil { t.Errorf("Git.GetTree returned error: %v", err) } want := Tree{ SHA: String("s"), Entries: []TreeEntry{ { Type: String("blob"), }, }, Truncated: Bool(true), } if !reflect.DeepEqual(*tree, want) { t.Errorf("Tree.Get returned %+v, want %+v", *tree, want) } } func TestGitService_GetTree_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Git.GetTree(context.Background(), "%", "%", "%", false) testURLParseError(t, err) } func TestGitService_CreateTree(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := []TreeEntry{ { Path: String("file.rb"), Mode: String("100644"), Type: String("blob"), SHA: String("7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b"), }, } mux.HandleFunc("/repos/o/r/git/trees", func(w http.ResponseWriter, r *http.Request) { v := new(createTree) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := &createTree{ BaseTree: "b", Entries: input, } if !reflect.DeepEqual(v, want) { t.Errorf("Git.CreateTree request body: %+v, want %+v", v, want) } fmt.Fprint(w, `{ "sha": "cd8274d15fa3ae2ab983129fb037999f264ba9a7", "tree": [ { "path": "file.rb", "mode": "100644", "type": "blob", "size": 132, "sha": "7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b" } ] }`) }) tree, _, err := client.Git.CreateTree(context.Background(), "o", "r", "b", input) if err != nil { t.Errorf("Git.CreateTree returned error: %v", err) } want := Tree{ String("cd8274d15fa3ae2ab983129fb037999f264ba9a7"), []TreeEntry{ { Path: String("file.rb"), Mode: String("100644"), Type: String("blob"), Size: Int(132), SHA: String("7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b"), }, }, nil, } if !reflect.DeepEqual(*tree, want) { t.Errorf("Git.CreateTree returned %+v, want %+v", *tree, want) } } func TestGitService_CreateTree_Content(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := []TreeEntry{ { Path: String("content.md"), Mode: String("100644"), Content: String("file content"), }, } mux.HandleFunc("/repos/o/r/git/trees", func(w http.ResponseWriter, r *http.Request) { v := new(createTree) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := &createTree{ BaseTree: "b", Entries: input, } if !reflect.DeepEqual(v, want) { t.Errorf("Git.CreateTree request body: %+v, want %+v", v, want) } fmt.Fprint(w, `{ "sha": "5c6780ad2c68743383b740fd1dab6f6a33202b11", "url": "https://api.github.com/repos/o/r/git/trees/5c6780ad2c68743383b740fd1dab6f6a33202b11", "tree": [ { "mode": "100644", "type": "blob", "sha": "aad8feacf6f8063150476a7b2bd9770f2794c08b", "path": "content.md", "size": 12, "url": "https://api.github.com/repos/o/r/git/blobs/aad8feacf6f8063150476a7b2bd9770f2794c08b" } ] }`) }) tree, _, err := client.Git.CreateTree(context.Background(), "o", "r", "b", input) if err != nil { t.Errorf("Git.CreateTree returned error: %v", err) } want := Tree{ String("5c6780ad2c68743383b740fd1dab6f6a33202b11"), []TreeEntry{ { Path: String("content.md"), Mode: String("100644"), Type: String("blob"), Size: Int(12), SHA: String("aad8feacf6f8063150476a7b2bd9770f2794c08b"), URL: String("https://api.github.com/repos/o/r/git/blobs/aad8feacf6f8063150476a7b2bd9770f2794c08b"), }, }, nil, } if !reflect.DeepEqual(*tree, want) { t.Errorf("Git.CreateTree returned %+v, want %+v", *tree, want) } } func TestGitService_CreateTree_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Git.CreateTree(context.Background(), "%", "%", "", nil) testURLParseError(t, err) } go-github-28.1.1/github/github-accessors.go000066400000000000000000011337171353501270500205640ustar00rootroot00000000000000// Copyright 2017 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. // Code generated by gen-accessors; DO NOT EDIT. package github import ( "encoding/json" "time" ) // GetRetryAfter returns the RetryAfter field if it's non-nil, zero value otherwise. func (a *AbuseRateLimitError) GetRetryAfter() time.Duration { if a == nil || a.RetryAfter == nil { return 0 } return *a.RetryAfter } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (a *AdminEnforcement) GetURL() string { if a == nil || a.URL == nil { return "" } return *a.URL } // GetComments returns the Comments field. func (a *AdminStats) GetComments() *CommentStats { if a == nil { return nil } return a.Comments } // GetGists returns the Gists field. func (a *AdminStats) GetGists() *GistStats { if a == nil { return nil } return a.Gists } // GetHooks returns the Hooks field. func (a *AdminStats) GetHooks() *HookStats { if a == nil { return nil } return a.Hooks } // GetIssues returns the Issues field. func (a *AdminStats) GetIssues() *IssueStats { if a == nil { return nil } return a.Issues } // GetMilestones returns the Milestones field. func (a *AdminStats) GetMilestones() *MilestoneStats { if a == nil { return nil } return a.Milestones } // GetOrgs returns the Orgs field. func (a *AdminStats) GetOrgs() *OrgStats { if a == nil { return nil } return a.Orgs } // GetPages returns the Pages field. func (a *AdminStats) GetPages() *PageStats { if a == nil { return nil } return a.Pages } // GetPulls returns the Pulls field. func (a *AdminStats) GetPulls() *PullStats { if a == nil { return nil } return a.Pulls } // GetRepos returns the Repos field. func (a *AdminStats) GetRepos() *RepoStats { if a == nil { return nil } return a.Repos } // GetUsers returns the Users field. func (a *AdminStats) GetUsers() *UserStats { if a == nil { return nil } return a.Users } // GetVerifiablePasswordAuthentication returns the VerifiablePasswordAuthentication field if it's non-nil, zero value otherwise. func (a *APIMeta) GetVerifiablePasswordAuthentication() bool { if a == nil || a.VerifiablePasswordAuthentication == nil { return false } return *a.VerifiablePasswordAuthentication } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (a *App) GetCreatedAt() Timestamp { if a == nil || a.CreatedAt == nil { return Timestamp{} } return *a.CreatedAt } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (a *App) GetDescription() string { if a == nil || a.Description == nil { return "" } return *a.Description } // GetExternalURL returns the ExternalURL field if it's non-nil, zero value otherwise. func (a *App) GetExternalURL() string { if a == nil || a.ExternalURL == nil { return "" } return *a.ExternalURL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (a *App) GetHTMLURL() string { if a == nil || a.HTMLURL == nil { return "" } return *a.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (a *App) GetID() int64 { if a == nil || a.ID == nil { return 0 } return *a.ID } // GetName returns the Name field if it's non-nil, zero value otherwise. func (a *App) GetName() string { if a == nil || a.Name == nil { return "" } return *a.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (a *App) GetNodeID() string { if a == nil || a.NodeID == nil { return "" } return *a.NodeID } // GetOwner returns the Owner field. func (a *App) GetOwner() *User { if a == nil { return nil } return a.Owner } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (a *App) GetUpdatedAt() Timestamp { if a == nil || a.UpdatedAt == nil { return Timestamp{} } return *a.UpdatedAt } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (a *Attachment) GetBody() string { if a == nil || a.Body == nil { return "" } return *a.Body } // GetID returns the ID field if it's non-nil, zero value otherwise. func (a *Attachment) GetID() int64 { if a == nil || a.ID == nil { return 0 } return *a.ID } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (a *Attachment) GetTitle() string { if a == nil || a.Title == nil { return "" } return *a.Title } // GetApp returns the App field. func (a *Authorization) GetApp() *AuthorizationApp { if a == nil { return nil } return a.App } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (a *Authorization) GetCreatedAt() Timestamp { if a == nil || a.CreatedAt == nil { return Timestamp{} } return *a.CreatedAt } // GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. func (a *Authorization) GetFingerprint() string { if a == nil || a.Fingerprint == nil { return "" } return *a.Fingerprint } // GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. func (a *Authorization) GetHashedToken() string { if a == nil || a.HashedToken == nil { return "" } return *a.HashedToken } // GetID returns the ID field if it's non-nil, zero value otherwise. func (a *Authorization) GetID() int64 { if a == nil || a.ID == nil { return 0 } return *a.ID } // GetNote returns the Note field if it's non-nil, zero value otherwise. func (a *Authorization) GetNote() string { if a == nil || a.Note == nil { return "" } return *a.Note } // GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. func (a *Authorization) GetNoteURL() string { if a == nil || a.NoteURL == nil { return "" } return *a.NoteURL } // GetToken returns the Token field if it's non-nil, zero value otherwise. func (a *Authorization) GetToken() string { if a == nil || a.Token == nil { return "" } return *a.Token } // GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. func (a *Authorization) GetTokenLastEight() string { if a == nil || a.TokenLastEight == nil { return "" } return *a.TokenLastEight } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (a *Authorization) GetUpdatedAt() Timestamp { if a == nil || a.UpdatedAt == nil { return Timestamp{} } return *a.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (a *Authorization) GetURL() string { if a == nil || a.URL == nil { return "" } return *a.URL } // GetUser returns the User field. func (a *Authorization) GetUser() *User { if a == nil { return nil } return a.User } // GetClientID returns the ClientID field if it's non-nil, zero value otherwise. func (a *AuthorizationApp) GetClientID() string { if a == nil || a.ClientID == nil { return "" } return *a.ClientID } // GetName returns the Name field if it's non-nil, zero value otherwise. func (a *AuthorizationApp) GetName() string { if a == nil || a.Name == nil { return "" } return *a.Name } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (a *AuthorizationApp) GetURL() string { if a == nil || a.URL == nil { return "" } return *a.URL } // GetClientID returns the ClientID field if it's non-nil, zero value otherwise. func (a *AuthorizationRequest) GetClientID() string { if a == nil || a.ClientID == nil { return "" } return *a.ClientID } // GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise. func (a *AuthorizationRequest) GetClientSecret() string { if a == nil || a.ClientSecret == nil { return "" } return *a.ClientSecret } // GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. func (a *AuthorizationRequest) GetFingerprint() string { if a == nil || a.Fingerprint == nil { return "" } return *a.Fingerprint } // GetNote returns the Note field if it's non-nil, zero value otherwise. func (a *AuthorizationRequest) GetNote() string { if a == nil || a.Note == nil { return "" } return *a.Note } // GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. func (a *AuthorizationRequest) GetNoteURL() string { if a == nil || a.NoteURL == nil { return "" } return *a.NoteURL } // GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. func (a *AuthorizationUpdateRequest) GetFingerprint() string { if a == nil || a.Fingerprint == nil { return "" } return *a.Fingerprint } // GetNote returns the Note field if it's non-nil, zero value otherwise. func (a *AuthorizationUpdateRequest) GetNote() string { if a == nil || a.Note == nil { return "" } return *a.Note } // GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. func (a *AuthorizationUpdateRequest) GetNoteURL() string { if a == nil || a.NoteURL == nil { return "" } return *a.NoteURL } // GetAppID returns the AppID field if it's non-nil, zero value otherwise. func (a *AutoTriggerCheck) GetAppID() int64 { if a == nil || a.AppID == nil { return 0 } return *a.AppID } // GetSetting returns the Setting field if it's non-nil, zero value otherwise. func (a *AutoTriggerCheck) GetSetting() bool { if a == nil || a.Setting == nil { return false } return *a.Setting } // GetContent returns the Content field if it's non-nil, zero value otherwise. func (b *Blob) GetContent() string { if b == nil || b.Content == nil { return "" } return *b.Content } // GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. func (b *Blob) GetEncoding() string { if b == nil || b.Encoding == nil { return "" } return *b.Encoding } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (b *Blob) GetNodeID() string { if b == nil || b.NodeID == nil { return "" } return *b.NodeID } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (b *Blob) GetSHA() string { if b == nil || b.SHA == nil { return "" } return *b.SHA } // GetSize returns the Size field if it's non-nil, zero value otherwise. func (b *Blob) GetSize() int { if b == nil || b.Size == nil { return 0 } return *b.Size } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (b *Blob) GetURL() string { if b == nil || b.URL == nil { return "" } return *b.URL } // GetCommit returns the Commit field. func (b *Branch) GetCommit() *RepositoryCommit { if b == nil { return nil } return b.Commit } // GetName returns the Name field if it's non-nil, zero value otherwise. func (b *Branch) GetName() string { if b == nil || b.Name == nil { return "" } return *b.Name } // GetProtected returns the Protected field if it's non-nil, zero value otherwise. func (b *Branch) GetProtected() bool { if b == nil || b.Protected == nil { return false } return *b.Protected } // GetCommit returns the Commit field. func (b *BranchCommit) GetCommit() *Commit { if b == nil { return nil } return b.Commit } // GetName returns the Name field if it's non-nil, zero value otherwise. func (b *BranchCommit) GetName() string { if b == nil || b.Name == nil { return "" } return *b.Name } // GetProtected returns the Protected field if it's non-nil, zero value otherwise. func (b *BranchCommit) GetProtected() string { if b == nil || b.Protected == nil { return "" } return *b.Protected } // GetApp returns the App field. func (c *CheckRun) GetApp() *App { if c == nil { return nil } return c.App } // GetCheckSuite returns the CheckSuite field. func (c *CheckRun) GetCheckSuite() *CheckSuite { if c == nil { return nil } return c.CheckSuite } // GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. func (c *CheckRun) GetCompletedAt() Timestamp { if c == nil || c.CompletedAt == nil { return Timestamp{} } return *c.CompletedAt } // GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. func (c *CheckRun) GetConclusion() string { if c == nil || c.Conclusion == nil { return "" } return *c.Conclusion } // GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. func (c *CheckRun) GetDetailsURL() string { if c == nil || c.DetailsURL == nil { return "" } return *c.DetailsURL } // GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. func (c *CheckRun) GetExternalID() string { if c == nil || c.ExternalID == nil { return "" } return *c.ExternalID } // GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. func (c *CheckRun) GetHeadSHA() string { if c == nil || c.HeadSHA == nil { return "" } return *c.HeadSHA } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (c *CheckRun) GetHTMLURL() string { if c == nil || c.HTMLURL == nil { return "" } return *c.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (c *CheckRun) GetID() int64 { if c == nil || c.ID == nil { return 0 } return *c.ID } // GetName returns the Name field if it's non-nil, zero value otherwise. func (c *CheckRun) GetName() string { if c == nil || c.Name == nil { return "" } return *c.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (c *CheckRun) GetNodeID() string { if c == nil || c.NodeID == nil { return "" } return *c.NodeID } // GetOutput returns the Output field. func (c *CheckRun) GetOutput() *CheckRunOutput { if c == nil { return nil } return c.Output } // GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. func (c *CheckRun) GetStartedAt() Timestamp { if c == nil || c.StartedAt == nil { return Timestamp{} } return *c.StartedAt } // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (c *CheckRun) GetStatus() string { if c == nil || c.Status == nil { return "" } return *c.Status } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (c *CheckRun) GetURL() string { if c == nil || c.URL == nil { return "" } return *c.URL } // GetAnnotationLevel returns the AnnotationLevel field if it's non-nil, zero value otherwise. func (c *CheckRunAnnotation) GetAnnotationLevel() string { if c == nil || c.AnnotationLevel == nil { return "" } return *c.AnnotationLevel } // GetBlobHRef returns the BlobHRef field if it's non-nil, zero value otherwise. func (c *CheckRunAnnotation) GetBlobHRef() string { if c == nil || c.BlobHRef == nil { return "" } return *c.BlobHRef } // GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. func (c *CheckRunAnnotation) GetEndColumn() int { if c == nil || c.EndColumn == nil { return 0 } return *c.EndColumn } // GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. func (c *CheckRunAnnotation) GetEndLine() int { if c == nil || c.EndLine == nil { return 0 } return *c.EndLine } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (c *CheckRunAnnotation) GetMessage() string { if c == nil || c.Message == nil { return "" } return *c.Message } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (c *CheckRunAnnotation) GetPath() string { if c == nil || c.Path == nil { return "" } return *c.Path } // GetRawDetails returns the RawDetails field if it's non-nil, zero value otherwise. func (c *CheckRunAnnotation) GetRawDetails() string { if c == nil || c.RawDetails == nil { return "" } return *c.RawDetails } // GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. func (c *CheckRunAnnotation) GetStartColumn() int { if c == nil || c.StartColumn == nil { return 0 } return *c.StartColumn } // GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. func (c *CheckRunAnnotation) GetStartLine() int { if c == nil || c.StartLine == nil { return 0 } return *c.StartLine } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (c *CheckRunAnnotation) GetTitle() string { if c == nil || c.Title == nil { return "" } return *c.Title } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (c *CheckRunEvent) GetAction() string { if c == nil || c.Action == nil { return "" } return *c.Action } // GetCheckRun returns the CheckRun field. func (c *CheckRunEvent) GetCheckRun() *CheckRun { if c == nil { return nil } return c.CheckRun } // GetInstallation returns the Installation field. func (c *CheckRunEvent) GetInstallation() *Installation { if c == nil { return nil } return c.Installation } // GetOrg returns the Org field. func (c *CheckRunEvent) GetOrg() *Organization { if c == nil { return nil } return c.Org } // GetRepo returns the Repo field. func (c *CheckRunEvent) GetRepo() *Repository { if c == nil { return nil } return c.Repo } // GetRequestedAction returns the RequestedAction field. func (c *CheckRunEvent) GetRequestedAction() *RequestedAction { if c == nil { return nil } return c.RequestedAction } // GetSender returns the Sender field. func (c *CheckRunEvent) GetSender() *User { if c == nil { return nil } return c.Sender } // GetAlt returns the Alt field if it's non-nil, zero value otherwise. func (c *CheckRunImage) GetAlt() string { if c == nil || c.Alt == nil { return "" } return *c.Alt } // GetCaption returns the Caption field if it's non-nil, zero value otherwise. func (c *CheckRunImage) GetCaption() string { if c == nil || c.Caption == nil { return "" } return *c.Caption } // GetImageURL returns the ImageURL field if it's non-nil, zero value otherwise. func (c *CheckRunImage) GetImageURL() string { if c == nil || c.ImageURL == nil { return "" } return *c.ImageURL } // GetAnnotationsCount returns the AnnotationsCount field if it's non-nil, zero value otherwise. func (c *CheckRunOutput) GetAnnotationsCount() int { if c == nil || c.AnnotationsCount == nil { return 0 } return *c.AnnotationsCount } // GetAnnotationsURL returns the AnnotationsURL field if it's non-nil, zero value otherwise. func (c *CheckRunOutput) GetAnnotationsURL() string { if c == nil || c.AnnotationsURL == nil { return "" } return *c.AnnotationsURL } // GetSummary returns the Summary field if it's non-nil, zero value otherwise. func (c *CheckRunOutput) GetSummary() string { if c == nil || c.Summary == nil { return "" } return *c.Summary } // GetText returns the Text field if it's non-nil, zero value otherwise. func (c *CheckRunOutput) GetText() string { if c == nil || c.Text == nil { return "" } return *c.Text } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (c *CheckRunOutput) GetTitle() string { if c == nil || c.Title == nil { return "" } return *c.Title } // GetAfterSHA returns the AfterSHA field if it's non-nil, zero value otherwise. func (c *CheckSuite) GetAfterSHA() string { if c == nil || c.AfterSHA == nil { return "" } return *c.AfterSHA } // GetApp returns the App field. func (c *CheckSuite) GetApp() *App { if c == nil { return nil } return c.App } // GetBeforeSHA returns the BeforeSHA field if it's non-nil, zero value otherwise. func (c *CheckSuite) GetBeforeSHA() string { if c == nil || c.BeforeSHA == nil { return "" } return *c.BeforeSHA } // GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. func (c *CheckSuite) GetConclusion() string { if c == nil || c.Conclusion == nil { return "" } return *c.Conclusion } // GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. func (c *CheckSuite) GetHeadBranch() string { if c == nil || c.HeadBranch == nil { return "" } return *c.HeadBranch } // GetHeadCommit returns the HeadCommit field. func (c *CheckSuite) GetHeadCommit() *Commit { if c == nil { return nil } return c.HeadCommit } // GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. func (c *CheckSuite) GetHeadSHA() string { if c == nil || c.HeadSHA == nil { return "" } return *c.HeadSHA } // GetID returns the ID field if it's non-nil, zero value otherwise. func (c *CheckSuite) GetID() int64 { if c == nil || c.ID == nil { return 0 } return *c.ID } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (c *CheckSuite) GetNodeID() string { if c == nil || c.NodeID == nil { return "" } return *c.NodeID } // GetRepository returns the Repository field. func (c *CheckSuite) GetRepository() *Repository { if c == nil { return nil } return c.Repository } // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (c *CheckSuite) GetStatus() string { if c == nil || c.Status == nil { return "" } return *c.Status } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (c *CheckSuite) GetURL() string { if c == nil || c.URL == nil { return "" } return *c.URL } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (c *CheckSuiteEvent) GetAction() string { if c == nil || c.Action == nil { return "" } return *c.Action } // GetCheckSuite returns the CheckSuite field. func (c *CheckSuiteEvent) GetCheckSuite() *CheckSuite { if c == nil { return nil } return c.CheckSuite } // GetInstallation returns the Installation field. func (c *CheckSuiteEvent) GetInstallation() *Installation { if c == nil { return nil } return c.Installation } // GetOrg returns the Org field. func (c *CheckSuiteEvent) GetOrg() *Organization { if c == nil { return nil } return c.Org } // GetRepo returns the Repo field. func (c *CheckSuiteEvent) GetRepo() *Repository { if c == nil { return nil } return c.Repo } // GetSender returns the Sender field. func (c *CheckSuiteEvent) GetSender() *User { if c == nil { return nil } return c.Sender } // GetPreferences returns the Preferences field. func (c *CheckSuitePreferenceResults) GetPreferences() *PreferenceList { if c == nil { return nil } return c.Preferences } // GetRepository returns the Repository field. func (c *CheckSuitePreferenceResults) GetRepository() *Repository { if c == nil { return nil } return c.Repository } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (c *CodeOfConduct) GetBody() string { if c == nil || c.Body == nil { return "" } return *c.Body } // GetKey returns the Key field if it's non-nil, zero value otherwise. func (c *CodeOfConduct) GetKey() string { if c == nil || c.Key == nil { return "" } return *c.Key } // GetName returns the Name field if it's non-nil, zero value otherwise. func (c *CodeOfConduct) GetName() string { if c == nil || c.Name == nil { return "" } return *c.Name } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (c *CodeOfConduct) GetURL() string { if c == nil || c.URL == nil { return "" } return *c.URL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (c *CodeResult) GetHTMLURL() string { if c == nil || c.HTMLURL == nil { return "" } return *c.HTMLURL } // GetName returns the Name field if it's non-nil, zero value otherwise. func (c *CodeResult) GetName() string { if c == nil || c.Name == nil { return "" } return *c.Name } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (c *CodeResult) GetPath() string { if c == nil || c.Path == nil { return "" } return *c.Path } // GetRepository returns the Repository field. func (c *CodeResult) GetRepository() *Repository { if c == nil { return nil } return c.Repository } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (c *CodeResult) GetSHA() string { if c == nil || c.SHA == nil { return "" } return *c.SHA } // GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. func (c *CodeSearchResult) GetIncompleteResults() bool { if c == nil || c.IncompleteResults == nil { return false } return *c.IncompleteResults } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (c *CodeSearchResult) GetTotal() int { if c == nil || c.Total == nil { return 0 } return *c.Total } // GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. func (c *CombinedStatus) GetCommitURL() string { if c == nil || c.CommitURL == nil { return "" } return *c.CommitURL } // GetName returns the Name field if it's non-nil, zero value otherwise. func (c *CombinedStatus) GetName() string { if c == nil || c.Name == nil { return "" } return *c.Name } // GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. func (c *CombinedStatus) GetRepositoryURL() string { if c == nil || c.RepositoryURL == nil { return "" } return *c.RepositoryURL } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (c *CombinedStatus) GetSHA() string { if c == nil || c.SHA == nil { return "" } return *c.SHA } // GetState returns the State field if it's non-nil, zero value otherwise. func (c *CombinedStatus) GetState() string { if c == nil || c.State == nil { return "" } return *c.State } // GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. func (c *CombinedStatus) GetTotalCount() int { if c == nil || c.TotalCount == nil { return 0 } return *c.TotalCount } // GetTotalCommitComments returns the TotalCommitComments field if it's non-nil, zero value otherwise. func (c *CommentStats) GetTotalCommitComments() int { if c == nil || c.TotalCommitComments == nil { return 0 } return *c.TotalCommitComments } // GetTotalGistComments returns the TotalGistComments field if it's non-nil, zero value otherwise. func (c *CommentStats) GetTotalGistComments() int { if c == nil || c.TotalGistComments == nil { return 0 } return *c.TotalGistComments } // GetTotalIssueComments returns the TotalIssueComments field if it's non-nil, zero value otherwise. func (c *CommentStats) GetTotalIssueComments() int { if c == nil || c.TotalIssueComments == nil { return 0 } return *c.TotalIssueComments } // GetTotalPullRequestComments returns the TotalPullRequestComments field if it's non-nil, zero value otherwise. func (c *CommentStats) GetTotalPullRequestComments() int { if c == nil || c.TotalPullRequestComments == nil { return 0 } return *c.TotalPullRequestComments } // GetAuthor returns the Author field. func (c *Commit) GetAuthor() *CommitAuthor { if c == nil { return nil } return c.Author } // GetCommentCount returns the CommentCount field if it's non-nil, zero value otherwise. func (c *Commit) GetCommentCount() int { if c == nil || c.CommentCount == nil { return 0 } return *c.CommentCount } // GetCommitter returns the Committer field. func (c *Commit) GetCommitter() *CommitAuthor { if c == nil { return nil } return c.Committer } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (c *Commit) GetHTMLURL() string { if c == nil || c.HTMLURL == nil { return "" } return *c.HTMLURL } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (c *Commit) GetMessage() string { if c == nil || c.Message == nil { return "" } return *c.Message } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (c *Commit) GetNodeID() string { if c == nil || c.NodeID == nil { return "" } return *c.NodeID } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (c *Commit) GetSHA() string { if c == nil || c.SHA == nil { return "" } return *c.SHA } // GetStats returns the Stats field. func (c *Commit) GetStats() *CommitStats { if c == nil { return nil } return c.Stats } // GetTree returns the Tree field. func (c *Commit) GetTree() *Tree { if c == nil { return nil } return c.Tree } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (c *Commit) GetURL() string { if c == nil || c.URL == nil { return "" } return *c.URL } // GetVerification returns the Verification field. func (c *Commit) GetVerification() *SignatureVerification { if c == nil { return nil } return c.Verification } // GetDate returns the Date field if it's non-nil, zero value otherwise. func (c *CommitAuthor) GetDate() time.Time { if c == nil || c.Date == nil { return time.Time{} } return *c.Date } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (c *CommitAuthor) GetEmail() string { if c == nil || c.Email == nil { return "" } return *c.Email } // GetLogin returns the Login field if it's non-nil, zero value otherwise. func (c *CommitAuthor) GetLogin() string { if c == nil || c.Login == nil { return "" } return *c.Login } // GetName returns the Name field if it's non-nil, zero value otherwise. func (c *CommitAuthor) GetName() string { if c == nil || c.Name == nil { return "" } return *c.Name } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (c *CommitCommentEvent) GetAction() string { if c == nil || c.Action == nil { return "" } return *c.Action } // GetComment returns the Comment field. func (c *CommitCommentEvent) GetComment() *RepositoryComment { if c == nil { return nil } return c.Comment } // GetInstallation returns the Installation field. func (c *CommitCommentEvent) GetInstallation() *Installation { if c == nil { return nil } return c.Installation } // GetRepo returns the Repo field. func (c *CommitCommentEvent) GetRepo() *Repository { if c == nil { return nil } return c.Repo } // GetSender returns the Sender field. func (c *CommitCommentEvent) GetSender() *User { if c == nil { return nil } return c.Sender } // GetAdditions returns the Additions field if it's non-nil, zero value otherwise. func (c *CommitFile) GetAdditions() int { if c == nil || c.Additions == nil { return 0 } return *c.Additions } // GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise. func (c *CommitFile) GetBlobURL() string { if c == nil || c.BlobURL == nil { return "" } return *c.BlobURL } // GetChanges returns the Changes field if it's non-nil, zero value otherwise. func (c *CommitFile) GetChanges() int { if c == nil || c.Changes == nil { return 0 } return *c.Changes } // GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. func (c *CommitFile) GetContentsURL() string { if c == nil || c.ContentsURL == nil { return "" } return *c.ContentsURL } // GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. func (c *CommitFile) GetDeletions() int { if c == nil || c.Deletions == nil { return 0 } return *c.Deletions } // GetFilename returns the Filename field if it's non-nil, zero value otherwise. func (c *CommitFile) GetFilename() string { if c == nil || c.Filename == nil { return "" } return *c.Filename } // GetPatch returns the Patch field if it's non-nil, zero value otherwise. func (c *CommitFile) GetPatch() string { if c == nil || c.Patch == nil { return "" } return *c.Patch } // GetPreviousFilename returns the PreviousFilename field if it's non-nil, zero value otherwise. func (c *CommitFile) GetPreviousFilename() string { if c == nil || c.PreviousFilename == nil { return "" } return *c.PreviousFilename } // GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. func (c *CommitFile) GetRawURL() string { if c == nil || c.RawURL == nil { return "" } return *c.RawURL } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (c *CommitFile) GetSHA() string { if c == nil || c.SHA == nil { return "" } return *c.SHA } // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (c *CommitFile) GetStatus() string { if c == nil || c.Status == nil { return "" } return *c.Status } // GetAuthor returns the Author field. func (c *CommitResult) GetAuthor() *User { if c == nil { return nil } return c.Author } // GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. func (c *CommitResult) GetCommentsURL() string { if c == nil || c.CommentsURL == nil { return "" } return *c.CommentsURL } // GetCommit returns the Commit field. func (c *CommitResult) GetCommit() *Commit { if c == nil { return nil } return c.Commit } // GetCommitter returns the Committer field. func (c *CommitResult) GetCommitter() *User { if c == nil { return nil } return c.Committer } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (c *CommitResult) GetHTMLURL() string { if c == nil || c.HTMLURL == nil { return "" } return *c.HTMLURL } // GetRepository returns the Repository field. func (c *CommitResult) GetRepository() *Repository { if c == nil { return nil } return c.Repository } // GetScore returns the Score field. func (c *CommitResult) GetScore() *float64 { if c == nil { return nil } return c.Score } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (c *CommitResult) GetSHA() string { if c == nil || c.SHA == nil { return "" } return *c.SHA } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (c *CommitResult) GetURL() string { if c == nil || c.URL == nil { return "" } return *c.URL } // GetAheadBy returns the AheadBy field if it's non-nil, zero value otherwise. func (c *CommitsComparison) GetAheadBy() int { if c == nil || c.AheadBy == nil { return 0 } return *c.AheadBy } // GetBaseCommit returns the BaseCommit field. func (c *CommitsComparison) GetBaseCommit() *RepositoryCommit { if c == nil { return nil } return c.BaseCommit } // GetBehindBy returns the BehindBy field if it's non-nil, zero value otherwise. func (c *CommitsComparison) GetBehindBy() int { if c == nil || c.BehindBy == nil { return 0 } return *c.BehindBy } // GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. func (c *CommitsComparison) GetDiffURL() string { if c == nil || c.DiffURL == nil { return "" } return *c.DiffURL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (c *CommitsComparison) GetHTMLURL() string { if c == nil || c.HTMLURL == nil { return "" } return *c.HTMLURL } // GetMergeBaseCommit returns the MergeBaseCommit field. func (c *CommitsComparison) GetMergeBaseCommit() *RepositoryCommit { if c == nil { return nil } return c.MergeBaseCommit } // GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. func (c *CommitsComparison) GetPatchURL() string { if c == nil || c.PatchURL == nil { return "" } return *c.PatchURL } // GetPermalinkURL returns the PermalinkURL field if it's non-nil, zero value otherwise. func (c *CommitsComparison) GetPermalinkURL() string { if c == nil || c.PermalinkURL == nil { return "" } return *c.PermalinkURL } // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (c *CommitsComparison) GetStatus() string { if c == nil || c.Status == nil { return "" } return *c.Status } // GetTotalCommits returns the TotalCommits field if it's non-nil, zero value otherwise. func (c *CommitsComparison) GetTotalCommits() int { if c == nil || c.TotalCommits == nil { return 0 } return *c.TotalCommits } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (c *CommitsComparison) GetURL() string { if c == nil || c.URL == nil { return "" } return *c.URL } // GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. func (c *CommitsSearchResult) GetIncompleteResults() bool { if c == nil || c.IncompleteResults == nil { return false } return *c.IncompleteResults } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (c *CommitsSearchResult) GetTotal() int { if c == nil || c.Total == nil { return 0 } return *c.Total } // GetAdditions returns the Additions field if it's non-nil, zero value otherwise. func (c *CommitStats) GetAdditions() int { if c == nil || c.Additions == nil { return 0 } return *c.Additions } // GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. func (c *CommitStats) GetDeletions() int { if c == nil || c.Deletions == nil { return 0 } return *c.Deletions } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (c *CommitStats) GetTotal() int { if c == nil || c.Total == nil { return 0 } return *c.Total } // GetCodeOfConduct returns the CodeOfConduct field. func (c *CommunityHealthFiles) GetCodeOfConduct() *Metric { if c == nil { return nil } return c.CodeOfConduct } // GetContributing returns the Contributing field. func (c *CommunityHealthFiles) GetContributing() *Metric { if c == nil { return nil } return c.Contributing } // GetIssueTemplate returns the IssueTemplate field. func (c *CommunityHealthFiles) GetIssueTemplate() *Metric { if c == nil { return nil } return c.IssueTemplate } // GetLicense returns the License field. func (c *CommunityHealthFiles) GetLicense() *Metric { if c == nil { return nil } return c.License } // GetPullRequestTemplate returns the PullRequestTemplate field. func (c *CommunityHealthFiles) GetPullRequestTemplate() *Metric { if c == nil { return nil } return c.PullRequestTemplate } // GetReadme returns the Readme field. func (c *CommunityHealthFiles) GetReadme() *Metric { if c == nil { return nil } return c.Readme } // GetFiles returns the Files field. func (c *CommunityHealthMetrics) GetFiles() *CommunityHealthFiles { if c == nil { return nil } return c.Files } // GetHealthPercentage returns the HealthPercentage field if it's non-nil, zero value otherwise. func (c *CommunityHealthMetrics) GetHealthPercentage() int { if c == nil || c.HealthPercentage == nil { return 0 } return *c.HealthPercentage } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (c *CommunityHealthMetrics) GetUpdatedAt() time.Time { if c == nil || c.UpdatedAt == nil { return time.Time{} } return *c.UpdatedAt } // GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetAvatarURL() string { if c == nil || c.AvatarURL == nil { return "" } return *c.AvatarURL } // GetContributions returns the Contributions field if it's non-nil, zero value otherwise. func (c *Contributor) GetContributions() int { if c == nil || c.Contributions == nil { return 0 } return *c.Contributions } // GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetEventsURL() string { if c == nil || c.EventsURL == nil { return "" } return *c.EventsURL } // GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetFollowersURL() string { if c == nil || c.FollowersURL == nil { return "" } return *c.FollowersURL } // GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetFollowingURL() string { if c == nil || c.FollowingURL == nil { return "" } return *c.FollowingURL } // GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetGistsURL() string { if c == nil || c.GistsURL == nil { return "" } return *c.GistsURL } // GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. func (c *Contributor) GetGravatarID() string { if c == nil || c.GravatarID == nil { return "" } return *c.GravatarID } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetHTMLURL() string { if c == nil || c.HTMLURL == nil { return "" } return *c.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (c *Contributor) GetID() int64 { if c == nil || c.ID == nil { return 0 } return *c.ID } // GetLogin returns the Login field if it's non-nil, zero value otherwise. func (c *Contributor) GetLogin() string { if c == nil || c.Login == nil { return "" } return *c.Login } // GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetOrganizationsURL() string { if c == nil || c.OrganizationsURL == nil { return "" } return *c.OrganizationsURL } // GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetReceivedEventsURL() string { if c == nil || c.ReceivedEventsURL == nil { return "" } return *c.ReceivedEventsURL } // GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetReposURL() string { if c == nil || c.ReposURL == nil { return "" } return *c.ReposURL } // GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. func (c *Contributor) GetSiteAdmin() bool { if c == nil || c.SiteAdmin == nil { return false } return *c.SiteAdmin } // GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetStarredURL() string { if c == nil || c.StarredURL == nil { return "" } return *c.StarredURL } // GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. func (c *Contributor) GetSubscriptionsURL() string { if c == nil || c.SubscriptionsURL == nil { return "" } return *c.SubscriptionsURL } // GetType returns the Type field if it's non-nil, zero value otherwise. func (c *Contributor) GetType() string { if c == nil || c.Type == nil { return "" } return *c.Type } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (c *Contributor) GetURL() string { if c == nil || c.URL == nil { return "" } return *c.URL } // GetAuthor returns the Author field. func (c *ContributorStats) GetAuthor() *Contributor { if c == nil { return nil } return c.Author } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (c *ContributorStats) GetTotal() int { if c == nil || c.Total == nil { return 0 } return *c.Total } // GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. func (c *CreateCheckRunOptions) GetCompletedAt() Timestamp { if c == nil || c.CompletedAt == nil { return Timestamp{} } return *c.CompletedAt } // GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. func (c *CreateCheckRunOptions) GetConclusion() string { if c == nil || c.Conclusion == nil { return "" } return *c.Conclusion } // GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. func (c *CreateCheckRunOptions) GetDetailsURL() string { if c == nil || c.DetailsURL == nil { return "" } return *c.DetailsURL } // GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. func (c *CreateCheckRunOptions) GetExternalID() string { if c == nil || c.ExternalID == nil { return "" } return *c.ExternalID } // GetOutput returns the Output field. func (c *CreateCheckRunOptions) GetOutput() *CheckRunOutput { if c == nil { return nil } return c.Output } // GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. func (c *CreateCheckRunOptions) GetStartedAt() Timestamp { if c == nil || c.StartedAt == nil { return Timestamp{} } return *c.StartedAt } // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (c *CreateCheckRunOptions) GetStatus() string { if c == nil || c.Status == nil { return "" } return *c.Status } // GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. func (c *CreateCheckSuiteOptions) GetHeadBranch() string { if c == nil || c.HeadBranch == nil { return "" } return *c.HeadBranch } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (c *CreateEvent) GetDescription() string { if c == nil || c.Description == nil { return "" } return *c.Description } // GetInstallation returns the Installation field. func (c *CreateEvent) GetInstallation() *Installation { if c == nil { return nil } return c.Installation } // GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. func (c *CreateEvent) GetMasterBranch() string { if c == nil || c.MasterBranch == nil { return "" } return *c.MasterBranch } // GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. func (c *CreateEvent) GetPusherType() string { if c == nil || c.PusherType == nil { return "" } return *c.PusherType } // GetRef returns the Ref field if it's non-nil, zero value otherwise. func (c *CreateEvent) GetRef() string { if c == nil || c.Ref == nil { return "" } return *c.Ref } // GetRefType returns the RefType field if it's non-nil, zero value otherwise. func (c *CreateEvent) GetRefType() string { if c == nil || c.RefType == nil { return "" } return *c.RefType } // GetRepo returns the Repo field. func (c *CreateEvent) GetRepo() *Repository { if c == nil { return nil } return c.Repo } // GetSender returns the Sender field. func (c *CreateEvent) GetSender() *User { if c == nil { return nil } return c.Sender } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (c *CreateOrgInvitationOptions) GetEmail() string { if c == nil || c.Email == nil { return "" } return *c.Email } // GetInviteeID returns the InviteeID field if it's non-nil, zero value otherwise. func (c *CreateOrgInvitationOptions) GetInviteeID() int64 { if c == nil || c.InviteeID == nil { return 0 } return *c.InviteeID } // GetRole returns the Role field if it's non-nil, zero value otherwise. func (c *CreateOrgInvitationOptions) GetRole() string { if c == nil || c.Role == nil { return "" } return *c.Role } // GetInstallation returns the Installation field. func (d *DeleteEvent) GetInstallation() *Installation { if d == nil { return nil } return d.Installation } // GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. func (d *DeleteEvent) GetPusherType() string { if d == nil || d.PusherType == nil { return "" } return *d.PusherType } // GetRef returns the Ref field if it's non-nil, zero value otherwise. func (d *DeleteEvent) GetRef() string { if d == nil || d.Ref == nil { return "" } return *d.Ref } // GetRefType returns the RefType field if it's non-nil, zero value otherwise. func (d *DeleteEvent) GetRefType() string { if d == nil || d.RefType == nil { return "" } return *d.RefType } // GetRepo returns the Repo field. func (d *DeleteEvent) GetRepo() *Repository { if d == nil { return nil } return d.Repo } // GetSender returns the Sender field. func (d *DeleteEvent) GetSender() *User { if d == nil { return nil } return d.Sender } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (d *DeployKeyEvent) GetAction() string { if d == nil || d.Action == nil { return "" } return *d.Action } // GetKey returns the Key field. func (d *DeployKeyEvent) GetKey() *Key { if d == nil { return nil } return d.Key } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (d *Deployment) GetCreatedAt() Timestamp { if d == nil || d.CreatedAt == nil { return Timestamp{} } return *d.CreatedAt } // GetCreator returns the Creator field. func (d *Deployment) GetCreator() *User { if d == nil { return nil } return d.Creator } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (d *Deployment) GetDescription() string { if d == nil || d.Description == nil { return "" } return *d.Description } // GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. func (d *Deployment) GetEnvironment() string { if d == nil || d.Environment == nil { return "" } return *d.Environment } // GetID returns the ID field if it's non-nil, zero value otherwise. func (d *Deployment) GetID() int64 { if d == nil || d.ID == nil { return 0 } return *d.ID } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (d *Deployment) GetNodeID() string { if d == nil || d.NodeID == nil { return "" } return *d.NodeID } // GetRef returns the Ref field if it's non-nil, zero value otherwise. func (d *Deployment) GetRef() string { if d == nil || d.Ref == nil { return "" } return *d.Ref } // GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. func (d *Deployment) GetRepositoryURL() string { if d == nil || d.RepositoryURL == nil { return "" } return *d.RepositoryURL } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (d *Deployment) GetSHA() string { if d == nil || d.SHA == nil { return "" } return *d.SHA } // GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. func (d *Deployment) GetStatusesURL() string { if d == nil || d.StatusesURL == nil { return "" } return *d.StatusesURL } // GetTask returns the Task field if it's non-nil, zero value otherwise. func (d *Deployment) GetTask() string { if d == nil || d.Task == nil { return "" } return *d.Task } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (d *Deployment) GetUpdatedAt() Timestamp { if d == nil || d.UpdatedAt == nil { return Timestamp{} } return *d.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (d *Deployment) GetURL() string { if d == nil || d.URL == nil { return "" } return *d.URL } // GetDeployment returns the Deployment field. func (d *DeploymentEvent) GetDeployment() *Deployment { if d == nil { return nil } return d.Deployment } // GetInstallation returns the Installation field. func (d *DeploymentEvent) GetInstallation() *Installation { if d == nil { return nil } return d.Installation } // GetRepo returns the Repo field. func (d *DeploymentEvent) GetRepo() *Repository { if d == nil { return nil } return d.Repo } // GetSender returns the Sender field. func (d *DeploymentEvent) GetSender() *User { if d == nil { return nil } return d.Sender } // GetAutoMerge returns the AutoMerge field if it's non-nil, zero value otherwise. func (d *DeploymentRequest) GetAutoMerge() bool { if d == nil || d.AutoMerge == nil { return false } return *d.AutoMerge } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (d *DeploymentRequest) GetDescription() string { if d == nil || d.Description == nil { return "" } return *d.Description } // GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. func (d *DeploymentRequest) GetEnvironment() string { if d == nil || d.Environment == nil { return "" } return *d.Environment } // GetPayload returns the Payload field if it's non-nil, zero value otherwise. func (d *DeploymentRequest) GetPayload() string { if d == nil || d.Payload == nil { return "" } return *d.Payload } // GetProductionEnvironment returns the ProductionEnvironment field if it's non-nil, zero value otherwise. func (d *DeploymentRequest) GetProductionEnvironment() bool { if d == nil || d.ProductionEnvironment == nil { return false } return *d.ProductionEnvironment } // GetRef returns the Ref field if it's non-nil, zero value otherwise. func (d *DeploymentRequest) GetRef() string { if d == nil || d.Ref == nil { return "" } return *d.Ref } // GetRequiredContexts returns the RequiredContexts field if it's non-nil, zero value otherwise. func (d *DeploymentRequest) GetRequiredContexts() []string { if d == nil || d.RequiredContexts == nil { return nil } return *d.RequiredContexts } // GetTask returns the Task field if it's non-nil, zero value otherwise. func (d *DeploymentRequest) GetTask() string { if d == nil || d.Task == nil { return "" } return *d.Task } // GetTransientEnvironment returns the TransientEnvironment field if it's non-nil, zero value otherwise. func (d *DeploymentRequest) GetTransientEnvironment() bool { if d == nil || d.TransientEnvironment == nil { return false } return *d.TransientEnvironment } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (d *DeploymentStatus) GetCreatedAt() Timestamp { if d == nil || d.CreatedAt == nil { return Timestamp{} } return *d.CreatedAt } // GetCreator returns the Creator field. func (d *DeploymentStatus) GetCreator() *User { if d == nil { return nil } return d.Creator } // GetDeploymentURL returns the DeploymentURL field if it's non-nil, zero value otherwise. func (d *DeploymentStatus) GetDeploymentURL() string { if d == nil || d.DeploymentURL == nil { return "" } return *d.DeploymentURL } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (d *DeploymentStatus) GetDescription() string { if d == nil || d.Description == nil { return "" } return *d.Description } // GetID returns the ID field if it's non-nil, zero value otherwise. func (d *DeploymentStatus) GetID() int64 { if d == nil || d.ID == nil { return 0 } return *d.ID } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (d *DeploymentStatus) GetNodeID() string { if d == nil || d.NodeID == nil { return "" } return *d.NodeID } // GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. func (d *DeploymentStatus) GetRepositoryURL() string { if d == nil || d.RepositoryURL == nil { return "" } return *d.RepositoryURL } // GetState returns the State field if it's non-nil, zero value otherwise. func (d *DeploymentStatus) GetState() string { if d == nil || d.State == nil { return "" } return *d.State } // GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. func (d *DeploymentStatus) GetTargetURL() string { if d == nil || d.TargetURL == nil { return "" } return *d.TargetURL } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (d *DeploymentStatus) GetUpdatedAt() Timestamp { if d == nil || d.UpdatedAt == nil { return Timestamp{} } return *d.UpdatedAt } // GetDeployment returns the Deployment field. func (d *DeploymentStatusEvent) GetDeployment() *Deployment { if d == nil { return nil } return d.Deployment } // GetDeploymentStatus returns the DeploymentStatus field. func (d *DeploymentStatusEvent) GetDeploymentStatus() *DeploymentStatus { if d == nil { return nil } return d.DeploymentStatus } // GetInstallation returns the Installation field. func (d *DeploymentStatusEvent) GetInstallation() *Installation { if d == nil { return nil } return d.Installation } // GetRepo returns the Repo field. func (d *DeploymentStatusEvent) GetRepo() *Repository { if d == nil { return nil } return d.Repo } // GetSender returns the Sender field. func (d *DeploymentStatusEvent) GetSender() *User { if d == nil { return nil } return d.Sender } // GetAutoInactive returns the AutoInactive field if it's non-nil, zero value otherwise. func (d *DeploymentStatusRequest) GetAutoInactive() bool { if d == nil || d.AutoInactive == nil { return false } return *d.AutoInactive } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (d *DeploymentStatusRequest) GetDescription() string { if d == nil || d.Description == nil { return "" } return *d.Description } // GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. func (d *DeploymentStatusRequest) GetEnvironment() string { if d == nil || d.Environment == nil { return "" } return *d.Environment } // GetEnvironmentURL returns the EnvironmentURL field if it's non-nil, zero value otherwise. func (d *DeploymentStatusRequest) GetEnvironmentURL() string { if d == nil || d.EnvironmentURL == nil { return "" } return *d.EnvironmentURL } // GetLogURL returns the LogURL field if it's non-nil, zero value otherwise. func (d *DeploymentStatusRequest) GetLogURL() string { if d == nil || d.LogURL == nil { return "" } return *d.LogURL } // GetState returns the State field if it's non-nil, zero value otherwise. func (d *DeploymentStatusRequest) GetState() string { if d == nil || d.State == nil { return "" } return *d.State } // GetAuthor returns the Author field. func (d *DiscussionComment) GetAuthor() *User { if d == nil { return nil } return d.Author } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetBody() string { if d == nil || d.Body == nil { return "" } return *d.Body } // GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetBodyHTML() string { if d == nil || d.BodyHTML == nil { return "" } return *d.BodyHTML } // GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetBodyVersion() string { if d == nil || d.BodyVersion == nil { return "" } return *d.BodyVersion } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetCreatedAt() Timestamp { if d == nil || d.CreatedAt == nil { return Timestamp{} } return *d.CreatedAt } // GetDiscussionURL returns the DiscussionURL field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetDiscussionURL() string { if d == nil || d.DiscussionURL == nil { return "" } return *d.DiscussionURL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetHTMLURL() string { if d == nil || d.HTMLURL == nil { return "" } return *d.HTMLURL } // GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetLastEditedAt() Timestamp { if d == nil || d.LastEditedAt == nil { return Timestamp{} } return *d.LastEditedAt } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetNodeID() string { if d == nil || d.NodeID == nil { return "" } return *d.NodeID } // GetNumber returns the Number field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetNumber() int { if d == nil || d.Number == nil { return 0 } return *d.Number } // GetReactions returns the Reactions field. func (d *DiscussionComment) GetReactions() *Reactions { if d == nil { return nil } return d.Reactions } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetUpdatedAt() Timestamp { if d == nil || d.UpdatedAt == nil { return Timestamp{} } return *d.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (d *DiscussionComment) GetURL() string { if d == nil || d.URL == nil { return "" } return *d.URL } // GetTeams returns the Teams field if it's non-nil, zero value otherwise. func (d *DismissalRestrictionsRequest) GetTeams() []string { if d == nil || d.Teams == nil { return nil } return *d.Teams } // GetUsers returns the Users field if it's non-nil, zero value otherwise. func (d *DismissalRestrictionsRequest) GetUsers() []string { if d == nil || d.Users == nil { return nil } return *d.Users } // GetDismissalCommitID returns the DismissalCommitID field if it's non-nil, zero value otherwise. func (d *DismissedReview) GetDismissalCommitID() string { if d == nil || d.DismissalCommitID == nil { return "" } return *d.DismissalCommitID } // GetDismissalMessage returns the DismissalMessage field if it's non-nil, zero value otherwise. func (d *DismissedReview) GetDismissalMessage() string { if d == nil || d.DismissalMessage == nil { return "" } return *d.DismissalMessage } // GetReviewID returns the ReviewID field if it's non-nil, zero value otherwise. func (d *DismissedReview) GetReviewID() int64 { if d == nil || d.ReviewID == nil { return 0 } return *d.ReviewID } // GetState returns the State field if it's non-nil, zero value otherwise. func (d *DismissedReview) GetState() string { if d == nil || d.State == nil { return "" } return *d.State } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (d *DraftReviewComment) GetBody() string { if d == nil || d.Body == nil { return "" } return *d.Body } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (d *DraftReviewComment) GetPath() string { if d == nil || d.Path == nil { return "" } return *d.Path } // GetPosition returns the Position field if it's non-nil, zero value otherwise. func (d *DraftReviewComment) GetPosition() int { if d == nil || d.Position == nil { return 0 } return *d.Position } // GetActor returns the Actor field. func (e *Event) GetActor() *User { if e == nil { return nil } return e.Actor } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (e *Event) GetCreatedAt() time.Time { if e == nil || e.CreatedAt == nil { return time.Time{} } return *e.CreatedAt } // GetID returns the ID field if it's non-nil, zero value otherwise. func (e *Event) GetID() string { if e == nil || e.ID == nil { return "" } return *e.ID } // GetOrg returns the Org field. func (e *Event) GetOrg() *Organization { if e == nil { return nil } return e.Org } // GetPublic returns the Public field if it's non-nil, zero value otherwise. func (e *Event) GetPublic() bool { if e == nil || e.Public == nil { return false } return *e.Public } // GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. func (e *Event) GetRawPayload() json.RawMessage { if e == nil || e.RawPayload == nil { return json.RawMessage{} } return *e.RawPayload } // GetRepo returns the Repo field. func (e *Event) GetRepo() *Repository { if e == nil { return nil } return e.Repo } // GetType returns the Type field if it's non-nil, zero value otherwise. func (e *Event) GetType() string { if e == nil || e.Type == nil { return "" } return *e.Type } // GetHRef returns the HRef field if it's non-nil, zero value otherwise. func (f *FeedLink) GetHRef() string { if f == nil || f.HRef == nil { return "" } return *f.HRef } // GetType returns the Type field if it's non-nil, zero value otherwise. func (f *FeedLink) GetType() string { if f == nil || f.Type == nil { return "" } return *f.Type } // GetCurrentUserActorURL returns the CurrentUserActorURL field if it's non-nil, zero value otherwise. func (f *Feeds) GetCurrentUserActorURL() string { if f == nil || f.CurrentUserActorURL == nil { return "" } return *f.CurrentUserActorURL } // GetCurrentUserOrganizationURL returns the CurrentUserOrganizationURL field if it's non-nil, zero value otherwise. func (f *Feeds) GetCurrentUserOrganizationURL() string { if f == nil || f.CurrentUserOrganizationURL == nil { return "" } return *f.CurrentUserOrganizationURL } // GetCurrentUserPublicURL returns the CurrentUserPublicURL field if it's non-nil, zero value otherwise. func (f *Feeds) GetCurrentUserPublicURL() string { if f == nil || f.CurrentUserPublicURL == nil { return "" } return *f.CurrentUserPublicURL } // GetCurrentUserURL returns the CurrentUserURL field if it's non-nil, zero value otherwise. func (f *Feeds) GetCurrentUserURL() string { if f == nil || f.CurrentUserURL == nil { return "" } return *f.CurrentUserURL } // GetTimelineURL returns the TimelineURL field if it's non-nil, zero value otherwise. func (f *Feeds) GetTimelineURL() string { if f == nil || f.TimelineURL == nil { return "" } return *f.TimelineURL } // GetUserURL returns the UserURL field if it's non-nil, zero value otherwise. func (f *Feeds) GetUserURL() string { if f == nil || f.UserURL == nil { return "" } return *f.UserURL } // GetForkee returns the Forkee field. func (f *ForkEvent) GetForkee() *Repository { if f == nil { return nil } return f.Forkee } // GetInstallation returns the Installation field. func (f *ForkEvent) GetInstallation() *Installation { if f == nil { return nil } return f.Installation } // GetRepo returns the Repo field. func (f *ForkEvent) GetRepo() *Repository { if f == nil { return nil } return f.Repo } // GetSender returns the Sender field. func (f *ForkEvent) GetSender() *User { if f == nil { return nil } return f.Sender } // GetComments returns the Comments field if it's non-nil, zero value otherwise. func (g *Gist) GetComments() int { if g == nil || g.Comments == nil { return 0 } return *g.Comments } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (g *Gist) GetCreatedAt() time.Time { if g == nil || g.CreatedAt == nil { return time.Time{} } return *g.CreatedAt } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (g *Gist) GetDescription() string { if g == nil || g.Description == nil { return "" } return *g.Description } // GetGitPullURL returns the GitPullURL field if it's non-nil, zero value otherwise. func (g *Gist) GetGitPullURL() string { if g == nil || g.GitPullURL == nil { return "" } return *g.GitPullURL } // GetGitPushURL returns the GitPushURL field if it's non-nil, zero value otherwise. func (g *Gist) GetGitPushURL() string { if g == nil || g.GitPushURL == nil { return "" } return *g.GitPushURL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (g *Gist) GetHTMLURL() string { if g == nil || g.HTMLURL == nil { return "" } return *g.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (g *Gist) GetID() string { if g == nil || g.ID == nil { return "" } return *g.ID } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (g *Gist) GetNodeID() string { if g == nil || g.NodeID == nil { return "" } return *g.NodeID } // GetOwner returns the Owner field. func (g *Gist) GetOwner() *User { if g == nil { return nil } return g.Owner } // GetPublic returns the Public field if it's non-nil, zero value otherwise. func (g *Gist) GetPublic() bool { if g == nil || g.Public == nil { return false } return *g.Public } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (g *Gist) GetUpdatedAt() time.Time { if g == nil || g.UpdatedAt == nil { return time.Time{} } return *g.UpdatedAt } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (g *GistComment) GetBody() string { if g == nil || g.Body == nil { return "" } return *g.Body } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (g *GistComment) GetCreatedAt() time.Time { if g == nil || g.CreatedAt == nil { return time.Time{} } return *g.CreatedAt } // GetID returns the ID field if it's non-nil, zero value otherwise. func (g *GistComment) GetID() int64 { if g == nil || g.ID == nil { return 0 } return *g.ID } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (g *GistComment) GetURL() string { if g == nil || g.URL == nil { return "" } return *g.URL } // GetUser returns the User field. func (g *GistComment) GetUser() *User { if g == nil { return nil } return g.User } // GetChangeStatus returns the ChangeStatus field. func (g *GistCommit) GetChangeStatus() *CommitStats { if g == nil { return nil } return g.ChangeStatus } // GetCommittedAt returns the CommittedAt field if it's non-nil, zero value otherwise. func (g *GistCommit) GetCommittedAt() Timestamp { if g == nil || g.CommittedAt == nil { return Timestamp{} } return *g.CommittedAt } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (g *GistCommit) GetNodeID() string { if g == nil || g.NodeID == nil { return "" } return *g.NodeID } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (g *GistCommit) GetURL() string { if g == nil || g.URL == nil { return "" } return *g.URL } // GetUser returns the User field. func (g *GistCommit) GetUser() *User { if g == nil { return nil } return g.User } // GetVersion returns the Version field if it's non-nil, zero value otherwise. func (g *GistCommit) GetVersion() string { if g == nil || g.Version == nil { return "" } return *g.Version } // GetContent returns the Content field if it's non-nil, zero value otherwise. func (g *GistFile) GetContent() string { if g == nil || g.Content == nil { return "" } return *g.Content } // GetFilename returns the Filename field if it's non-nil, zero value otherwise. func (g *GistFile) GetFilename() string { if g == nil || g.Filename == nil { return "" } return *g.Filename } // GetLanguage returns the Language field if it's non-nil, zero value otherwise. func (g *GistFile) GetLanguage() string { if g == nil || g.Language == nil { return "" } return *g.Language } // GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. func (g *GistFile) GetRawURL() string { if g == nil || g.RawURL == nil { return "" } return *g.RawURL } // GetSize returns the Size field if it's non-nil, zero value otherwise. func (g *GistFile) GetSize() int { if g == nil || g.Size == nil { return 0 } return *g.Size } // GetType returns the Type field if it's non-nil, zero value otherwise. func (g *GistFile) GetType() string { if g == nil || g.Type == nil { return "" } return *g.Type } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (g *GistFork) GetCreatedAt() Timestamp { if g == nil || g.CreatedAt == nil { return Timestamp{} } return *g.CreatedAt } // GetID returns the ID field if it's non-nil, zero value otherwise. func (g *GistFork) GetID() string { if g == nil || g.ID == nil { return "" } return *g.ID } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (g *GistFork) GetNodeID() string { if g == nil || g.NodeID == nil { return "" } return *g.NodeID } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (g *GistFork) GetUpdatedAt() Timestamp { if g == nil || g.UpdatedAt == nil { return Timestamp{} } return *g.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (g *GistFork) GetURL() string { if g == nil || g.URL == nil { return "" } return *g.URL } // GetUser returns the User field. func (g *GistFork) GetUser() *User { if g == nil { return nil } return g.User } // GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. func (g *GistStats) GetPrivateGists() int { if g == nil || g.PrivateGists == nil { return 0 } return *g.PrivateGists } // GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. func (g *GistStats) GetPublicGists() int { if g == nil || g.PublicGists == nil { return 0 } return *g.PublicGists } // GetTotalGists returns the TotalGists field if it's non-nil, zero value otherwise. func (g *GistStats) GetTotalGists() int { if g == nil || g.TotalGists == nil { return 0 } return *g.TotalGists } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (g *GitHubAppAuthorizationEvent) GetAction() string { if g == nil || g.Action == nil { return "" } return *g.Action } // GetSender returns the Sender field. func (g *GitHubAppAuthorizationEvent) GetSender() *User { if g == nil { return nil } return g.Sender } // GetName returns the Name field if it's non-nil, zero value otherwise. func (g *Gitignore) GetName() string { if g == nil || g.Name == nil { return "" } return *g.Name } // GetSource returns the Source field if it's non-nil, zero value otherwise. func (g *Gitignore) GetSource() string { if g == nil || g.Source == nil { return "" } return *g.Source } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (g *GitObject) GetSHA() string { if g == nil || g.SHA == nil { return "" } return *g.SHA } // GetType returns the Type field if it's non-nil, zero value otherwise. func (g *GitObject) GetType() string { if g == nil || g.Type == nil { return "" } return *g.Type } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (g *GitObject) GetURL() string { if g == nil || g.URL == nil { return "" } return *g.URL } // GetInstallation returns the Installation field. func (g *GollumEvent) GetInstallation() *Installation { if g == nil { return nil } return g.Installation } // GetRepo returns the Repo field. func (g *GollumEvent) GetRepo() *Repository { if g == nil { return nil } return g.Repo } // GetSender returns the Sender field. func (g *GollumEvent) GetSender() *User { if g == nil { return nil } return g.Sender } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (g *GPGEmail) GetEmail() string { if g == nil || g.Email == nil { return "" } return *g.Email } // GetVerified returns the Verified field if it's non-nil, zero value otherwise. func (g *GPGEmail) GetVerified() bool { if g == nil || g.Verified == nil { return false } return *g.Verified } // GetCanCertify returns the CanCertify field if it's non-nil, zero value otherwise. func (g *GPGKey) GetCanCertify() bool { if g == nil || g.CanCertify == nil { return false } return *g.CanCertify } // GetCanEncryptComms returns the CanEncryptComms field if it's non-nil, zero value otherwise. func (g *GPGKey) GetCanEncryptComms() bool { if g == nil || g.CanEncryptComms == nil { return false } return *g.CanEncryptComms } // GetCanEncryptStorage returns the CanEncryptStorage field if it's non-nil, zero value otherwise. func (g *GPGKey) GetCanEncryptStorage() bool { if g == nil || g.CanEncryptStorage == nil { return false } return *g.CanEncryptStorage } // GetCanSign returns the CanSign field if it's non-nil, zero value otherwise. func (g *GPGKey) GetCanSign() bool { if g == nil || g.CanSign == nil { return false } return *g.CanSign } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (g *GPGKey) GetCreatedAt() time.Time { if g == nil || g.CreatedAt == nil { return time.Time{} } return *g.CreatedAt } // GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. func (g *GPGKey) GetExpiresAt() time.Time { if g == nil || g.ExpiresAt == nil { return time.Time{} } return *g.ExpiresAt } // GetID returns the ID field if it's non-nil, zero value otherwise. func (g *GPGKey) GetID() int64 { if g == nil || g.ID == nil { return 0 } return *g.ID } // GetKeyID returns the KeyID field if it's non-nil, zero value otherwise. func (g *GPGKey) GetKeyID() string { if g == nil || g.KeyID == nil { return "" } return *g.KeyID } // GetPrimaryKeyID returns the PrimaryKeyID field if it's non-nil, zero value otherwise. func (g *GPGKey) GetPrimaryKeyID() int64 { if g == nil || g.PrimaryKeyID == nil { return 0 } return *g.PrimaryKeyID } // GetPublicKey returns the PublicKey field if it's non-nil, zero value otherwise. func (g *GPGKey) GetPublicKey() string { if g == nil || g.PublicKey == nil { return "" } return *g.PublicKey } // GetApp returns the App field. func (g *Grant) GetApp() *AuthorizationApp { if g == nil { return nil } return g.App } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (g *Grant) GetCreatedAt() Timestamp { if g == nil || g.CreatedAt == nil { return Timestamp{} } return *g.CreatedAt } // GetID returns the ID field if it's non-nil, zero value otherwise. func (g *Grant) GetID() int64 { if g == nil || g.ID == nil { return 0 } return *g.ID } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (g *Grant) GetUpdatedAt() Timestamp { if g == nil || g.UpdatedAt == nil { return Timestamp{} } return *g.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (g *Grant) GetURL() string { if g == nil || g.URL == nil { return "" } return *g.URL } // GetActive returns the Active field if it's non-nil, zero value otherwise. func (h *Hook) GetActive() bool { if h == nil || h.Active == nil { return false } return *h.Active } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (h *Hook) GetCreatedAt() time.Time { if h == nil || h.CreatedAt == nil { return time.Time{} } return *h.CreatedAt } // GetID returns the ID field if it's non-nil, zero value otherwise. func (h *Hook) GetID() int64 { if h == nil || h.ID == nil { return 0 } return *h.ID } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (h *Hook) GetUpdatedAt() time.Time { if h == nil || h.UpdatedAt == nil { return time.Time{} } return *h.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (h *Hook) GetURL() string { if h == nil || h.URL == nil { return "" } return *h.URL } // GetActiveHooks returns the ActiveHooks field if it's non-nil, zero value otherwise. func (h *HookStats) GetActiveHooks() int { if h == nil || h.ActiveHooks == nil { return 0 } return *h.ActiveHooks } // GetInactiveHooks returns the InactiveHooks field if it's non-nil, zero value otherwise. func (h *HookStats) GetInactiveHooks() int { if h == nil || h.InactiveHooks == nil { return 0 } return *h.InactiveHooks } // GetTotalHooks returns the TotalHooks field if it's non-nil, zero value otherwise. func (h *HookStats) GetTotalHooks() int { if h == nil || h.TotalHooks == nil { return 0 } return *h.TotalHooks } // GetGroupDescription returns the GroupDescription field if it's non-nil, zero value otherwise. func (i *IDPGroup) GetGroupDescription() string { if i == nil || i.GroupDescription == nil { return "" } return *i.GroupDescription } // GetGroupID returns the GroupID field if it's non-nil, zero value otherwise. func (i *IDPGroup) GetGroupID() string { if i == nil || i.GroupID == nil { return "" } return *i.GroupID } // GetGroupName returns the GroupName field if it's non-nil, zero value otherwise. func (i *IDPGroup) GetGroupName() string { if i == nil || i.GroupName == nil { return "" } return *i.GroupName } // GetAuthorsCount returns the AuthorsCount field if it's non-nil, zero value otherwise. func (i *Import) GetAuthorsCount() int { if i == nil || i.AuthorsCount == nil { return 0 } return *i.AuthorsCount } // GetAuthorsURL returns the AuthorsURL field if it's non-nil, zero value otherwise. func (i *Import) GetAuthorsURL() string { if i == nil || i.AuthorsURL == nil { return "" } return *i.AuthorsURL } // GetCommitCount returns the CommitCount field if it's non-nil, zero value otherwise. func (i *Import) GetCommitCount() int { if i == nil || i.CommitCount == nil { return 0 } return *i.CommitCount } // GetFailedStep returns the FailedStep field if it's non-nil, zero value otherwise. func (i *Import) GetFailedStep() string { if i == nil || i.FailedStep == nil { return "" } return *i.FailedStep } // GetHasLargeFiles returns the HasLargeFiles field if it's non-nil, zero value otherwise. func (i *Import) GetHasLargeFiles() bool { if i == nil || i.HasLargeFiles == nil { return false } return *i.HasLargeFiles } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (i *Import) GetHTMLURL() string { if i == nil || i.HTMLURL == nil { return "" } return *i.HTMLURL } // GetHumanName returns the HumanName field if it's non-nil, zero value otherwise. func (i *Import) GetHumanName() string { if i == nil || i.HumanName == nil { return "" } return *i.HumanName } // GetLargeFilesCount returns the LargeFilesCount field if it's non-nil, zero value otherwise. func (i *Import) GetLargeFilesCount() int { if i == nil || i.LargeFilesCount == nil { return 0 } return *i.LargeFilesCount } // GetLargeFilesSize returns the LargeFilesSize field if it's non-nil, zero value otherwise. func (i *Import) GetLargeFilesSize() int { if i == nil || i.LargeFilesSize == nil { return 0 } return *i.LargeFilesSize } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (i *Import) GetMessage() string { if i == nil || i.Message == nil { return "" } return *i.Message } // GetPercent returns the Percent field if it's non-nil, zero value otherwise. func (i *Import) GetPercent() int { if i == nil || i.Percent == nil { return 0 } return *i.Percent } // GetPushPercent returns the PushPercent field if it's non-nil, zero value otherwise. func (i *Import) GetPushPercent() int { if i == nil || i.PushPercent == nil { return 0 } return *i.PushPercent } // GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. func (i *Import) GetRepositoryURL() string { if i == nil || i.RepositoryURL == nil { return "" } return *i.RepositoryURL } // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (i *Import) GetStatus() string { if i == nil || i.Status == nil { return "" } return *i.Status } // GetStatusText returns the StatusText field if it's non-nil, zero value otherwise. func (i *Import) GetStatusText() string { if i == nil || i.StatusText == nil { return "" } return *i.StatusText } // GetTFVCProject returns the TFVCProject field if it's non-nil, zero value otherwise. func (i *Import) GetTFVCProject() string { if i == nil || i.TFVCProject == nil { return "" } return *i.TFVCProject } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (i *Import) GetURL() string { if i == nil || i.URL == nil { return "" } return *i.URL } // GetUseLFS returns the UseLFS field if it's non-nil, zero value otherwise. func (i *Import) GetUseLFS() string { if i == nil || i.UseLFS == nil { return "" } return *i.UseLFS } // GetVCS returns the VCS field if it's non-nil, zero value otherwise. func (i *Import) GetVCS() string { if i == nil || i.VCS == nil { return "" } return *i.VCS } // GetVCSPassword returns the VCSPassword field if it's non-nil, zero value otherwise. func (i *Import) GetVCSPassword() string { if i == nil || i.VCSPassword == nil { return "" } return *i.VCSPassword } // GetVCSURL returns the VCSURL field if it's non-nil, zero value otherwise. func (i *Import) GetVCSURL() string { if i == nil || i.VCSURL == nil { return "" } return *i.VCSURL } // GetVCSUsername returns the VCSUsername field if it's non-nil, zero value otherwise. func (i *Import) GetVCSUsername() string { if i == nil || i.VCSUsername == nil { return "" } return *i.VCSUsername } // GetAccessTokensURL returns the AccessTokensURL field if it's non-nil, zero value otherwise. func (i *Installation) GetAccessTokensURL() string { if i == nil || i.AccessTokensURL == nil { return "" } return *i.AccessTokensURL } // GetAccount returns the Account field. func (i *Installation) GetAccount() *User { if i == nil { return nil } return i.Account } // GetAppID returns the AppID field if it's non-nil, zero value otherwise. func (i *Installation) GetAppID() int64 { if i == nil || i.AppID == nil { return 0 } return *i.AppID } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (i *Installation) GetCreatedAt() Timestamp { if i == nil || i.CreatedAt == nil { return Timestamp{} } return *i.CreatedAt } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (i *Installation) GetHTMLURL() string { if i == nil || i.HTMLURL == nil { return "" } return *i.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (i *Installation) GetID() int64 { if i == nil || i.ID == nil { return 0 } return *i.ID } // GetPermissions returns the Permissions field. func (i *Installation) GetPermissions() *InstallationPermissions { if i == nil { return nil } return i.Permissions } // GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. func (i *Installation) GetRepositoriesURL() string { if i == nil || i.RepositoriesURL == nil { return "" } return *i.RepositoriesURL } // GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. func (i *Installation) GetRepositorySelection() string { if i == nil || i.RepositorySelection == nil { return "" } return *i.RepositorySelection } // GetSingleFileName returns the SingleFileName field if it's non-nil, zero value otherwise. func (i *Installation) GetSingleFileName() string { if i == nil || i.SingleFileName == nil { return "" } return *i.SingleFileName } // GetTargetID returns the TargetID field if it's non-nil, zero value otherwise. func (i *Installation) GetTargetID() int64 { if i == nil || i.TargetID == nil { return 0 } return *i.TargetID } // GetTargetType returns the TargetType field if it's non-nil, zero value otherwise. func (i *Installation) GetTargetType() string { if i == nil || i.TargetType == nil { return "" } return *i.TargetType } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (i *Installation) GetUpdatedAt() Timestamp { if i == nil || i.UpdatedAt == nil { return Timestamp{} } return *i.UpdatedAt } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (i *InstallationEvent) GetAction() string { if i == nil || i.Action == nil { return "" } return *i.Action } // GetInstallation returns the Installation field. func (i *InstallationEvent) GetInstallation() *Installation { if i == nil { return nil } return i.Installation } // GetSender returns the Sender field. func (i *InstallationEvent) GetSender() *User { if i == nil { return nil } return i.Sender } // GetAdministration returns the Administration field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetAdministration() string { if i == nil || i.Administration == nil { return "" } return *i.Administration } // GetChecks returns the Checks field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetChecks() string { if i == nil || i.Checks == nil { return "" } return *i.Checks } // GetContentReferences returns the ContentReferences field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetContentReferences() string { if i == nil || i.ContentReferences == nil { return "" } return *i.ContentReferences } // GetContents returns the Contents field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetContents() string { if i == nil || i.Contents == nil { return "" } return *i.Contents } // GetDeployments returns the Deployments field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetDeployments() string { if i == nil || i.Deployments == nil { return "" } return *i.Deployments } // GetIssues returns the Issues field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetIssues() string { if i == nil || i.Issues == nil { return "" } return *i.Issues } // GetMembers returns the Members field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetMembers() string { if i == nil || i.Members == nil { return "" } return *i.Members } // GetMetadata returns the Metadata field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetMetadata() string { if i == nil || i.Metadata == nil { return "" } return *i.Metadata } // GetOrganizationAdministration returns the OrganizationAdministration field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetOrganizationAdministration() string { if i == nil || i.OrganizationAdministration == nil { return "" } return *i.OrganizationAdministration } // GetOrganizationHooks returns the OrganizationHooks field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetOrganizationHooks() string { if i == nil || i.OrganizationHooks == nil { return "" } return *i.OrganizationHooks } // GetOrganizationPlan returns the OrganizationPlan field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetOrganizationPlan() string { if i == nil || i.OrganizationPlan == nil { return "" } return *i.OrganizationPlan } // GetOrganizationPreReceiveHooks returns the OrganizationPreReceiveHooks field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetOrganizationPreReceiveHooks() string { if i == nil || i.OrganizationPreReceiveHooks == nil { return "" } return *i.OrganizationPreReceiveHooks } // GetOrganizationProjects returns the OrganizationProjects field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetOrganizationProjects() string { if i == nil || i.OrganizationProjects == nil { return "" } return *i.OrganizationProjects } // GetOrganizationUserBlocking returns the OrganizationUserBlocking field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetOrganizationUserBlocking() string { if i == nil || i.OrganizationUserBlocking == nil { return "" } return *i.OrganizationUserBlocking } // GetPackages returns the Packages field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetPackages() string { if i == nil || i.Packages == nil { return "" } return *i.Packages } // GetPages returns the Pages field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetPages() string { if i == nil || i.Pages == nil { return "" } return *i.Pages } // GetPullRequests returns the PullRequests field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetPullRequests() string { if i == nil || i.PullRequests == nil { return "" } return *i.PullRequests } // GetRepositoryHooks returns the RepositoryHooks field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetRepositoryHooks() string { if i == nil || i.RepositoryHooks == nil { return "" } return *i.RepositoryHooks } // GetRepositoryPreReceiveHooks returns the RepositoryPreReceiveHooks field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetRepositoryPreReceiveHooks() string { if i == nil || i.RepositoryPreReceiveHooks == nil { return "" } return *i.RepositoryPreReceiveHooks } // GetRepositoryProjects returns the RepositoryProjects field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetRepositoryProjects() string { if i == nil || i.RepositoryProjects == nil { return "" } return *i.RepositoryProjects } // GetSingleFile returns the SingleFile field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetSingleFile() string { if i == nil || i.SingleFile == nil { return "" } return *i.SingleFile } // GetStatuses returns the Statuses field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetStatuses() string { if i == nil || i.Statuses == nil { return "" } return *i.Statuses } // GetTeamDiscussions returns the TeamDiscussions field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetTeamDiscussions() string { if i == nil || i.TeamDiscussions == nil { return "" } return *i.TeamDiscussions } // GetVulnerabilityAlerts returns the VulnerabilityAlerts field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetVulnerabilityAlerts() string { if i == nil || i.VulnerabilityAlerts == nil { return "" } return *i.VulnerabilityAlerts } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (i *InstallationRepositoriesEvent) GetAction() string { if i == nil || i.Action == nil { return "" } return *i.Action } // GetInstallation returns the Installation field. func (i *InstallationRepositoriesEvent) GetInstallation() *Installation { if i == nil { return nil } return i.Installation } // GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. func (i *InstallationRepositoriesEvent) GetRepositorySelection() string { if i == nil || i.RepositorySelection == nil { return "" } return *i.RepositorySelection } // GetSender returns the Sender field. func (i *InstallationRepositoriesEvent) GetSender() *User { if i == nil { return nil } return i.Sender } // GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. func (i *InstallationToken) GetExpiresAt() time.Time { if i == nil || i.ExpiresAt == nil { return time.Time{} } return *i.ExpiresAt } // GetPermissions returns the Permissions field. func (i *InstallationToken) GetPermissions() *InstallationPermissions { if i == nil { return nil } return i.Permissions } // GetToken returns the Token field if it's non-nil, zero value otherwise. func (i *InstallationToken) GetToken() string { if i == nil || i.Token == nil { return "" } return *i.Token } // GetPermissions returns the Permissions field. func (i *InstallationTokenOptions) GetPermissions() *InstallationPermissions { if i == nil { return nil } return i.Permissions } // GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. func (i *InteractionRestriction) GetExpiresAt() Timestamp { if i == nil || i.ExpiresAt == nil { return Timestamp{} } return *i.ExpiresAt } // GetLimit returns the Limit field if it's non-nil, zero value otherwise. func (i *InteractionRestriction) GetLimit() string { if i == nil || i.Limit == nil { return "" } return *i.Limit } // GetOrigin returns the Origin field if it's non-nil, zero value otherwise. func (i *InteractionRestriction) GetOrigin() string { if i == nil || i.Origin == nil { return "" } return *i.Origin } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (i *Invitation) GetCreatedAt() time.Time { if i == nil || i.CreatedAt == nil { return time.Time{} } return *i.CreatedAt } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (i *Invitation) GetEmail() string { if i == nil || i.Email == nil { return "" } return *i.Email } // GetID returns the ID field if it's non-nil, zero value otherwise. func (i *Invitation) GetID() int64 { if i == nil || i.ID == nil { return 0 } return *i.ID } // GetInvitationTeamURL returns the InvitationTeamURL field if it's non-nil, zero value otherwise. func (i *Invitation) GetInvitationTeamURL() string { if i == nil || i.InvitationTeamURL == nil { return "" } return *i.InvitationTeamURL } // GetInviter returns the Inviter field. func (i *Invitation) GetInviter() *User { if i == nil { return nil } return i.Inviter } // GetLogin returns the Login field if it's non-nil, zero value otherwise. func (i *Invitation) GetLogin() string { if i == nil || i.Login == nil { return "" } return *i.Login } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (i *Invitation) GetNodeID() string { if i == nil || i.NodeID == nil { return "" } return *i.NodeID } // GetRole returns the Role field if it's non-nil, zero value otherwise. func (i *Invitation) GetRole() string { if i == nil || i.Role == nil { return "" } return *i.Role } // GetTeamCount returns the TeamCount field if it's non-nil, zero value otherwise. func (i *Invitation) GetTeamCount() int { if i == nil || i.TeamCount == nil { return 0 } return *i.TeamCount } // GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. func (i *Issue) GetActiveLockReason() string { if i == nil || i.ActiveLockReason == nil { return "" } return *i.ActiveLockReason } // GetAssignee returns the Assignee field. func (i *Issue) GetAssignee() *User { if i == nil { return nil } return i.Assignee } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (i *Issue) GetBody() string { if i == nil || i.Body == nil { return "" } return *i.Body } // GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. func (i *Issue) GetClosedAt() time.Time { if i == nil || i.ClosedAt == nil { return time.Time{} } return *i.ClosedAt } // GetClosedBy returns the ClosedBy field. func (i *Issue) GetClosedBy() *User { if i == nil { return nil } return i.ClosedBy } // GetComments returns the Comments field if it's non-nil, zero value otherwise. func (i *Issue) GetComments() int { if i == nil || i.Comments == nil { return 0 } return *i.Comments } // GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. func (i *Issue) GetCommentsURL() string { if i == nil || i.CommentsURL == nil { return "" } return *i.CommentsURL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (i *Issue) GetCreatedAt() time.Time { if i == nil || i.CreatedAt == nil { return time.Time{} } return *i.CreatedAt } // GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. func (i *Issue) GetEventsURL() string { if i == nil || i.EventsURL == nil { return "" } return *i.EventsURL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (i *Issue) GetHTMLURL() string { if i == nil || i.HTMLURL == nil { return "" } return *i.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (i *Issue) GetID() int64 { if i == nil || i.ID == nil { return 0 } return *i.ID } // GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. func (i *Issue) GetLabelsURL() string { if i == nil || i.LabelsURL == nil { return "" } return *i.LabelsURL } // GetLocked returns the Locked field if it's non-nil, zero value otherwise. func (i *Issue) GetLocked() bool { if i == nil || i.Locked == nil { return false } return *i.Locked } // GetMilestone returns the Milestone field. func (i *Issue) GetMilestone() *Milestone { if i == nil { return nil } return i.Milestone } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (i *Issue) GetNodeID() string { if i == nil || i.NodeID == nil { return "" } return *i.NodeID } // GetNumber returns the Number field if it's non-nil, zero value otherwise. func (i *Issue) GetNumber() int { if i == nil || i.Number == nil { return 0 } return *i.Number } // GetPullRequestLinks returns the PullRequestLinks field. func (i *Issue) GetPullRequestLinks() *PullRequestLinks { if i == nil { return nil } return i.PullRequestLinks } // GetReactions returns the Reactions field. func (i *Issue) GetReactions() *Reactions { if i == nil { return nil } return i.Reactions } // GetRepository returns the Repository field. func (i *Issue) GetRepository() *Repository { if i == nil { return nil } return i.Repository } // GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. func (i *Issue) GetRepositoryURL() string { if i == nil || i.RepositoryURL == nil { return "" } return *i.RepositoryURL } // GetState returns the State field if it's non-nil, zero value otherwise. func (i *Issue) GetState() string { if i == nil || i.State == nil { return "" } return *i.State } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (i *Issue) GetTitle() string { if i == nil || i.Title == nil { return "" } return *i.Title } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (i *Issue) GetUpdatedAt() time.Time { if i == nil || i.UpdatedAt == nil { return time.Time{} } return *i.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (i *Issue) GetURL() string { if i == nil || i.URL == nil { return "" } return *i.URL } // GetUser returns the User field. func (i *Issue) GetUser() *User { if i == nil { return nil } return i.User } // GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. func (i *IssueComment) GetAuthorAssociation() string { if i == nil || i.AuthorAssociation == nil { return "" } return *i.AuthorAssociation } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (i *IssueComment) GetBody() string { if i == nil || i.Body == nil { return "" } return *i.Body } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (i *IssueComment) GetCreatedAt() time.Time { if i == nil || i.CreatedAt == nil { return time.Time{} } return *i.CreatedAt } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (i *IssueComment) GetHTMLURL() string { if i == nil || i.HTMLURL == nil { return "" } return *i.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (i *IssueComment) GetID() int64 { if i == nil || i.ID == nil { return 0 } return *i.ID } // GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. func (i *IssueComment) GetIssueURL() string { if i == nil || i.IssueURL == nil { return "" } return *i.IssueURL } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (i *IssueComment) GetNodeID() string { if i == nil || i.NodeID == nil { return "" } return *i.NodeID } // GetReactions returns the Reactions field. func (i *IssueComment) GetReactions() *Reactions { if i == nil { return nil } return i.Reactions } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (i *IssueComment) GetUpdatedAt() time.Time { if i == nil || i.UpdatedAt == nil { return time.Time{} } return *i.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (i *IssueComment) GetURL() string { if i == nil || i.URL == nil { return "" } return *i.URL } // GetUser returns the User field. func (i *IssueComment) GetUser() *User { if i == nil { return nil } return i.User } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (i *IssueCommentEvent) GetAction() string { if i == nil || i.Action == nil { return "" } return *i.Action } // GetChanges returns the Changes field. func (i *IssueCommentEvent) GetChanges() *EditChange { if i == nil { return nil } return i.Changes } // GetComment returns the Comment field. func (i *IssueCommentEvent) GetComment() *IssueComment { if i == nil { return nil } return i.Comment } // GetInstallation returns the Installation field. func (i *IssueCommentEvent) GetInstallation() *Installation { if i == nil { return nil } return i.Installation } // GetIssue returns the Issue field. func (i *IssueCommentEvent) GetIssue() *Issue { if i == nil { return nil } return i.Issue } // GetRepo returns the Repo field. func (i *IssueCommentEvent) GetRepo() *Repository { if i == nil { return nil } return i.Repo } // GetSender returns the Sender field. func (i *IssueCommentEvent) GetSender() *User { if i == nil { return nil } return i.Sender } // GetActor returns the Actor field. func (i *IssueEvent) GetActor() *User { if i == nil { return nil } return i.Actor } // GetAssignee returns the Assignee field. func (i *IssueEvent) GetAssignee() *User { if i == nil { return nil } return i.Assignee } // GetAssigner returns the Assigner field. func (i *IssueEvent) GetAssigner() *User { if i == nil { return nil } return i.Assigner } // GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. func (i *IssueEvent) GetCommitID() string { if i == nil || i.CommitID == nil { return "" } return *i.CommitID } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (i *IssueEvent) GetCreatedAt() time.Time { if i == nil || i.CreatedAt == nil { return time.Time{} } return *i.CreatedAt } // GetDismissedReview returns the DismissedReview field. func (i *IssueEvent) GetDismissedReview() *DismissedReview { if i == nil { return nil } return i.DismissedReview } // GetEvent returns the Event field if it's non-nil, zero value otherwise. func (i *IssueEvent) GetEvent() string { if i == nil || i.Event == nil { return "" } return *i.Event } // GetID returns the ID field if it's non-nil, zero value otherwise. func (i *IssueEvent) GetID() int64 { if i == nil || i.ID == nil { return 0 } return *i.ID } // GetIssue returns the Issue field. func (i *IssueEvent) GetIssue() *Issue { if i == nil { return nil } return i.Issue } // GetLabel returns the Label field. func (i *IssueEvent) GetLabel() *Label { if i == nil { return nil } return i.Label } // GetLockReason returns the LockReason field if it's non-nil, zero value otherwise. func (i *IssueEvent) GetLockReason() string { if i == nil || i.LockReason == nil { return "" } return *i.LockReason } // GetMilestone returns the Milestone field. func (i *IssueEvent) GetMilestone() *Milestone { if i == nil { return nil } return i.Milestone } // GetProjectCard returns the ProjectCard field. func (i *IssueEvent) GetProjectCard() *ProjectCard { if i == nil { return nil } return i.ProjectCard } // GetRename returns the Rename field. func (i *IssueEvent) GetRename() *Rename { if i == nil { return nil } return i.Rename } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (i *IssueEvent) GetURL() string { if i == nil || i.URL == nil { return "" } return *i.URL } // GetAssignee returns the Assignee field if it's non-nil, zero value otherwise. func (i *IssueRequest) GetAssignee() string { if i == nil || i.Assignee == nil { return "" } return *i.Assignee } // GetAssignees returns the Assignees field if it's non-nil, zero value otherwise. func (i *IssueRequest) GetAssignees() []string { if i == nil || i.Assignees == nil { return nil } return *i.Assignees } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (i *IssueRequest) GetBody() string { if i == nil || i.Body == nil { return "" } return *i.Body } // GetLabels returns the Labels field if it's non-nil, zero value otherwise. func (i *IssueRequest) GetLabels() []string { if i == nil || i.Labels == nil { return nil } return *i.Labels } // GetMilestone returns the Milestone field if it's non-nil, zero value otherwise. func (i *IssueRequest) GetMilestone() int { if i == nil || i.Milestone == nil { return 0 } return *i.Milestone } // GetState returns the State field if it's non-nil, zero value otherwise. func (i *IssueRequest) GetState() string { if i == nil || i.State == nil { return "" } return *i.State } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (i *IssueRequest) GetTitle() string { if i == nil || i.Title == nil { return "" } return *i.Title } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (i *IssuesEvent) GetAction() string { if i == nil || i.Action == nil { return "" } return *i.Action } // GetAssignee returns the Assignee field. func (i *IssuesEvent) GetAssignee() *User { if i == nil { return nil } return i.Assignee } // GetChanges returns the Changes field. func (i *IssuesEvent) GetChanges() *EditChange { if i == nil { return nil } return i.Changes } // GetInstallation returns the Installation field. func (i *IssuesEvent) GetInstallation() *Installation { if i == nil { return nil } return i.Installation } // GetIssue returns the Issue field. func (i *IssuesEvent) GetIssue() *Issue { if i == nil { return nil } return i.Issue } // GetLabel returns the Label field. func (i *IssuesEvent) GetLabel() *Label { if i == nil { return nil } return i.Label } // GetRepo returns the Repo field. func (i *IssuesEvent) GetRepo() *Repository { if i == nil { return nil } return i.Repo } // GetSender returns the Sender field. func (i *IssuesEvent) GetSender() *User { if i == nil { return nil } return i.Sender } // GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. func (i *IssuesSearchResult) GetIncompleteResults() bool { if i == nil || i.IncompleteResults == nil { return false } return *i.IncompleteResults } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (i *IssuesSearchResult) GetTotal() int { if i == nil || i.Total == nil { return 0 } return *i.Total } // GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. func (i *IssueStats) GetClosedIssues() int { if i == nil || i.ClosedIssues == nil { return 0 } return *i.ClosedIssues } // GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. func (i *IssueStats) GetOpenIssues() int { if i == nil || i.OpenIssues == nil { return 0 } return *i.OpenIssues } // GetTotalIssues returns the TotalIssues field if it's non-nil, zero value otherwise. func (i *IssueStats) GetTotalIssues() int { if i == nil || i.TotalIssues == nil { return 0 } return *i.TotalIssues } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (k *Key) GetCreatedAt() Timestamp { if k == nil || k.CreatedAt == nil { return Timestamp{} } return *k.CreatedAt } // GetID returns the ID field if it's non-nil, zero value otherwise. func (k *Key) GetID() int64 { if k == nil || k.ID == nil { return 0 } return *k.ID } // GetKey returns the Key field if it's non-nil, zero value otherwise. func (k *Key) GetKey() string { if k == nil || k.Key == nil { return "" } return *k.Key } // GetReadOnly returns the ReadOnly field if it's non-nil, zero value otherwise. func (k *Key) GetReadOnly() bool { if k == nil || k.ReadOnly == nil { return false } return *k.ReadOnly } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (k *Key) GetTitle() string { if k == nil || k.Title == nil { return "" } return *k.Title } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (k *Key) GetURL() string { if k == nil || k.URL == nil { return "" } return *k.URL } // GetColor returns the Color field if it's non-nil, zero value otherwise. func (l *Label) GetColor() string { if l == nil || l.Color == nil { return "" } return *l.Color } // GetDefault returns the Default field if it's non-nil, zero value otherwise. func (l *Label) GetDefault() bool { if l == nil || l.Default == nil { return false } return *l.Default } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (l *Label) GetDescription() string { if l == nil || l.Description == nil { return "" } return *l.Description } // GetID returns the ID field if it's non-nil, zero value otherwise. func (l *Label) GetID() int64 { if l == nil || l.ID == nil { return 0 } return *l.ID } // GetName returns the Name field if it's non-nil, zero value otherwise. func (l *Label) GetName() string { if l == nil || l.Name == nil { return "" } return *l.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (l *Label) GetNodeID() string { if l == nil || l.NodeID == nil { return "" } return *l.NodeID } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (l *Label) GetURL() string { if l == nil || l.URL == nil { return "" } return *l.URL } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (l *LabelEvent) GetAction() string { if l == nil || l.Action == nil { return "" } return *l.Action } // GetChanges returns the Changes field. func (l *LabelEvent) GetChanges() *EditChange { if l == nil { return nil } return l.Changes } // GetInstallation returns the Installation field. func (l *LabelEvent) GetInstallation() *Installation { if l == nil { return nil } return l.Installation } // GetLabel returns the Label field. func (l *LabelEvent) GetLabel() *Label { if l == nil { return nil } return l.Label } // GetOrg returns the Org field. func (l *LabelEvent) GetOrg() *Organization { if l == nil { return nil } return l.Org } // GetRepo returns the Repo field. func (l *LabelEvent) GetRepo() *Repository { if l == nil { return nil } return l.Repo } // GetColor returns the Color field if it's non-nil, zero value otherwise. func (l *LabelResult) GetColor() string { if l == nil || l.Color == nil { return "" } return *l.Color } // GetDefault returns the Default field if it's non-nil, zero value otherwise. func (l *LabelResult) GetDefault() bool { if l == nil || l.Default == nil { return false } return *l.Default } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (l *LabelResult) GetDescription() string { if l == nil || l.Description == nil { return "" } return *l.Description } // GetID returns the ID field if it's non-nil, zero value otherwise. func (l *LabelResult) GetID() int64 { if l == nil || l.ID == nil { return 0 } return *l.ID } // GetName returns the Name field if it's non-nil, zero value otherwise. func (l *LabelResult) GetName() string { if l == nil || l.Name == nil { return "" } return *l.Name } // GetScore returns the Score field. func (l *LabelResult) GetScore() *float64 { if l == nil { return nil } return l.Score } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (l *LabelResult) GetURL() string { if l == nil || l.URL == nil { return "" } return *l.URL } // GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. func (l *LabelsSearchResult) GetIncompleteResults() bool { if l == nil || l.IncompleteResults == nil { return false } return *l.IncompleteResults } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (l *LabelsSearchResult) GetTotal() int { if l == nil || l.Total == nil { return 0 } return *l.Total } // GetOID returns the OID field if it's non-nil, zero value otherwise. func (l *LargeFile) GetOID() string { if l == nil || l.OID == nil { return "" } return *l.OID } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (l *LargeFile) GetPath() string { if l == nil || l.Path == nil { return "" } return *l.Path } // GetRefName returns the RefName field if it's non-nil, zero value otherwise. func (l *LargeFile) GetRefName() string { if l == nil || l.RefName == nil { return "" } return *l.RefName } // GetSize returns the Size field if it's non-nil, zero value otherwise. func (l *LargeFile) GetSize() int { if l == nil || l.Size == nil { return 0 } return *l.Size } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (l *License) GetBody() string { if l == nil || l.Body == nil { return "" } return *l.Body } // GetConditions returns the Conditions field if it's non-nil, zero value otherwise. func (l *License) GetConditions() []string { if l == nil || l.Conditions == nil { return nil } return *l.Conditions } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (l *License) GetDescription() string { if l == nil || l.Description == nil { return "" } return *l.Description } // GetFeatured returns the Featured field if it's non-nil, zero value otherwise. func (l *License) GetFeatured() bool { if l == nil || l.Featured == nil { return false } return *l.Featured } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (l *License) GetHTMLURL() string { if l == nil || l.HTMLURL == nil { return "" } return *l.HTMLURL } // GetImplementation returns the Implementation field if it's non-nil, zero value otherwise. func (l *License) GetImplementation() string { if l == nil || l.Implementation == nil { return "" } return *l.Implementation } // GetKey returns the Key field if it's non-nil, zero value otherwise. func (l *License) GetKey() string { if l == nil || l.Key == nil { return "" } return *l.Key } // GetLimitations returns the Limitations field if it's non-nil, zero value otherwise. func (l *License) GetLimitations() []string { if l == nil || l.Limitations == nil { return nil } return *l.Limitations } // GetName returns the Name field if it's non-nil, zero value otherwise. func (l *License) GetName() string { if l == nil || l.Name == nil { return "" } return *l.Name } // GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. func (l *License) GetPermissions() []string { if l == nil || l.Permissions == nil { return nil } return *l.Permissions } // GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. func (l *License) GetSPDXID() string { if l == nil || l.SPDXID == nil { return "" } return *l.SPDXID } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (l *License) GetURL() string { if l == nil || l.URL == nil { return "" } return *l.URL } // GetCheckName returns the CheckName field if it's non-nil, zero value otherwise. func (l *ListCheckRunsOptions) GetCheckName() string { if l == nil || l.CheckName == nil { return "" } return *l.CheckName } // GetFilter returns the Filter field if it's non-nil, zero value otherwise. func (l *ListCheckRunsOptions) GetFilter() string { if l == nil || l.Filter == nil { return "" } return *l.Filter } // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (l *ListCheckRunsOptions) GetStatus() string { if l == nil || l.Status == nil { return "" } return *l.Status } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (l *ListCheckRunsResults) GetTotal() int { if l == nil || l.Total == nil { return 0 } return *l.Total } // GetAppID returns the AppID field if it's non-nil, zero value otherwise. func (l *ListCheckSuiteOptions) GetAppID() int { if l == nil || l.AppID == nil { return 0 } return *l.AppID } // GetCheckName returns the CheckName field if it's non-nil, zero value otherwise. func (l *ListCheckSuiteOptions) GetCheckName() string { if l == nil || l.CheckName == nil { return "" } return *l.CheckName } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (l *ListCheckSuiteResults) GetTotal() int { if l == nil || l.Total == nil { return 0 } return *l.Total } // GetAffiliation returns the Affiliation field if it's non-nil, zero value otherwise. func (l *ListCollaboratorOptions) GetAffiliation() string { if l == nil || l.Affiliation == nil { return "" } return *l.Affiliation } // GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. func (m *MarketplacePendingChange) GetEffectiveDate() Timestamp { if m == nil || m.EffectiveDate == nil { return Timestamp{} } return *m.EffectiveDate } // GetID returns the ID field if it's non-nil, zero value otherwise. func (m *MarketplacePendingChange) GetID() int64 { if m == nil || m.ID == nil { return 0 } return *m.ID } // GetPlan returns the Plan field. func (m *MarketplacePendingChange) GetPlan() *MarketplacePlan { if m == nil { return nil } return m.Plan } // GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise. func (m *MarketplacePendingChange) GetUnitCount() int { if m == nil || m.UnitCount == nil { return 0 } return *m.UnitCount } // GetAccountsURL returns the AccountsURL field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetAccountsURL() string { if m == nil || m.AccountsURL == nil { return "" } return *m.AccountsURL } // GetBullets returns the Bullets field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetBullets() []string { if m == nil || m.Bullets == nil { return nil } return *m.Bullets } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetDescription() string { if m == nil || m.Description == nil { return "" } return *m.Description } // GetHasFreeTrial returns the HasFreeTrial field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetHasFreeTrial() bool { if m == nil || m.HasFreeTrial == nil { return false } return *m.HasFreeTrial } // GetID returns the ID field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetID() int64 { if m == nil || m.ID == nil { return 0 } return *m.ID } // GetMonthlyPriceInCents returns the MonthlyPriceInCents field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetMonthlyPriceInCents() int { if m == nil || m.MonthlyPriceInCents == nil { return 0 } return *m.MonthlyPriceInCents } // GetName returns the Name field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetName() string { if m == nil || m.Name == nil { return "" } return *m.Name } // GetPriceModel returns the PriceModel field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetPriceModel() string { if m == nil || m.PriceModel == nil { return "" } return *m.PriceModel } // GetState returns the State field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetState() string { if m == nil || m.State == nil { return "" } return *m.State } // GetUnitName returns the UnitName field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetUnitName() string { if m == nil || m.UnitName == nil { return "" } return *m.UnitName } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetURL() string { if m == nil || m.URL == nil { return "" } return *m.URL } // GetYearlyPriceInCents returns the YearlyPriceInCents field if it's non-nil, zero value otherwise. func (m *MarketplacePlan) GetYearlyPriceInCents() int { if m == nil || m.YearlyPriceInCents == nil { return 0 } return *m.YearlyPriceInCents } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (m *MarketplacePlanAccount) GetEmail() string { if m == nil || m.Email == nil { return "" } return *m.Email } // GetID returns the ID field if it's non-nil, zero value otherwise. func (m *MarketplacePlanAccount) GetID() int64 { if m == nil || m.ID == nil { return 0 } return *m.ID } // GetLogin returns the Login field if it's non-nil, zero value otherwise. func (m *MarketplacePlanAccount) GetLogin() string { if m == nil || m.Login == nil { return "" } return *m.Login } // GetMarketplacePendingChange returns the MarketplacePendingChange field. func (m *MarketplacePlanAccount) GetMarketplacePendingChange() *MarketplacePendingChange { if m == nil { return nil } return m.MarketplacePendingChange } // GetMarketplacePurchase returns the MarketplacePurchase field. func (m *MarketplacePlanAccount) GetMarketplacePurchase() *MarketplacePurchase { if m == nil { return nil } return m.MarketplacePurchase } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (m *MarketplacePlanAccount) GetNodeID() string { if m == nil || m.NodeID == nil { return "" } return *m.NodeID } // GetOrganizationBillingEmail returns the OrganizationBillingEmail field if it's non-nil, zero value otherwise. func (m *MarketplacePlanAccount) GetOrganizationBillingEmail() string { if m == nil || m.OrganizationBillingEmail == nil { return "" } return *m.OrganizationBillingEmail } // GetType returns the Type field if it's non-nil, zero value otherwise. func (m *MarketplacePlanAccount) GetType() string { if m == nil || m.Type == nil { return "" } return *m.Type } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (m *MarketplacePlanAccount) GetURL() string { if m == nil || m.URL == nil { return "" } return *m.URL } // GetAccount returns the Account field. func (m *MarketplacePurchase) GetAccount() *MarketplacePlanAccount { if m == nil { return nil } return m.Account } // GetBillingCycle returns the BillingCycle field if it's non-nil, zero value otherwise. func (m *MarketplacePurchase) GetBillingCycle() string { if m == nil || m.BillingCycle == nil { return "" } return *m.BillingCycle } // GetFreeTrialEndsOn returns the FreeTrialEndsOn field if it's non-nil, zero value otherwise. func (m *MarketplacePurchase) GetFreeTrialEndsOn() Timestamp { if m == nil || m.FreeTrialEndsOn == nil { return Timestamp{} } return *m.FreeTrialEndsOn } // GetNextBillingDate returns the NextBillingDate field if it's non-nil, zero value otherwise. func (m *MarketplacePurchase) GetNextBillingDate() Timestamp { if m == nil || m.NextBillingDate == nil { return Timestamp{} } return *m.NextBillingDate } // GetOnFreeTrial returns the OnFreeTrial field if it's non-nil, zero value otherwise. func (m *MarketplacePurchase) GetOnFreeTrial() bool { if m == nil || m.OnFreeTrial == nil { return false } return *m.OnFreeTrial } // GetPlan returns the Plan field. func (m *MarketplacePurchase) GetPlan() *MarketplacePlan { if m == nil { return nil } return m.Plan } // GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise. func (m *MarketplacePurchase) GetUnitCount() int { if m == nil || m.UnitCount == nil { return 0 } return *m.UnitCount } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (m *MarketplacePurchaseEvent) GetAction() string { if m == nil || m.Action == nil { return "" } return *m.Action } // GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. func (m *MarketplacePurchaseEvent) GetEffectiveDate() Timestamp { if m == nil || m.EffectiveDate == nil { return Timestamp{} } return *m.EffectiveDate } // GetInstallation returns the Installation field. func (m *MarketplacePurchaseEvent) GetInstallation() *Installation { if m == nil { return nil } return m.Installation } // GetMarketplacePurchase returns the MarketplacePurchase field. func (m *MarketplacePurchaseEvent) GetMarketplacePurchase() *MarketplacePurchase { if m == nil { return nil } return m.MarketplacePurchase } // GetPreviousMarketplacePurchase returns the PreviousMarketplacePurchase field. func (m *MarketplacePurchaseEvent) GetPreviousMarketplacePurchase() *MarketplacePurchase { if m == nil { return nil } return m.PreviousMarketplacePurchase } // GetSender returns the Sender field. func (m *MarketplacePurchaseEvent) GetSender() *User { if m == nil { return nil } return m.Sender } // GetText returns the Text field if it's non-nil, zero value otherwise. func (m *Match) GetText() string { if m == nil || m.Text == nil { return "" } return *m.Text } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (m *MemberEvent) GetAction() string { if m == nil || m.Action == nil { return "" } return *m.Action } // GetInstallation returns the Installation field. func (m *MemberEvent) GetInstallation() *Installation { if m == nil { return nil } return m.Installation } // GetMember returns the Member field. func (m *MemberEvent) GetMember() *User { if m == nil { return nil } return m.Member } // GetRepo returns the Repo field. func (m *MemberEvent) GetRepo() *Repository { if m == nil { return nil } return m.Repo } // GetSender returns the Sender field. func (m *MemberEvent) GetSender() *User { if m == nil { return nil } return m.Sender } // GetOrganization returns the Organization field. func (m *Membership) GetOrganization() *Organization { if m == nil { return nil } return m.Organization } // GetOrganizationURL returns the OrganizationURL field if it's non-nil, zero value otherwise. func (m *Membership) GetOrganizationURL() string { if m == nil || m.OrganizationURL == nil { return "" } return *m.OrganizationURL } // GetRole returns the Role field if it's non-nil, zero value otherwise. func (m *Membership) GetRole() string { if m == nil || m.Role == nil { return "" } return *m.Role } // GetState returns the State field if it's non-nil, zero value otherwise. func (m *Membership) GetState() string { if m == nil || m.State == nil { return "" } return *m.State } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (m *Membership) GetURL() string { if m == nil || m.URL == nil { return "" } return *m.URL } // GetUser returns the User field. func (m *Membership) GetUser() *User { if m == nil { return nil } return m.User } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (m *MembershipEvent) GetAction() string { if m == nil || m.Action == nil { return "" } return *m.Action } // GetInstallation returns the Installation field. func (m *MembershipEvent) GetInstallation() *Installation { if m == nil { return nil } return m.Installation } // GetMember returns the Member field. func (m *MembershipEvent) GetMember() *User { if m == nil { return nil } return m.Member } // GetOrg returns the Org field. func (m *MembershipEvent) GetOrg() *Organization { if m == nil { return nil } return m.Org } // GetScope returns the Scope field if it's non-nil, zero value otherwise. func (m *MembershipEvent) GetScope() string { if m == nil || m.Scope == nil { return "" } return *m.Scope } // GetSender returns the Sender field. func (m *MembershipEvent) GetSender() *User { if m == nil { return nil } return m.Sender } // GetTeam returns the Team field. func (m *MembershipEvent) GetTeam() *Team { if m == nil { return nil } return m.Team } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (m *MetaEvent) GetAction() string { if m == nil || m.Action == nil { return "" } return *m.Action } // GetHook returns the Hook field. func (m *MetaEvent) GetHook() *Hook { if m == nil { return nil } return m.Hook } // GetHookID returns the HookID field if it's non-nil, zero value otherwise. func (m *MetaEvent) GetHookID() int64 { if m == nil || m.HookID == nil { return 0 } return *m.HookID } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (m *Metric) GetHTMLURL() string { if m == nil || m.HTMLURL == nil { return "" } return *m.HTMLURL } // GetKey returns the Key field if it's non-nil, zero value otherwise. func (m *Metric) GetKey() string { if m == nil || m.Key == nil { return "" } return *m.Key } // GetName returns the Name field if it's non-nil, zero value otherwise. func (m *Metric) GetName() string { if m == nil || m.Name == nil { return "" } return *m.Name } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (m *Metric) GetURL() string { if m == nil || m.URL == nil { return "" } return *m.URL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (m *Migration) GetCreatedAt() string { if m == nil || m.CreatedAt == nil { return "" } return *m.CreatedAt } // GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. func (m *Migration) GetExcludeAttachments() bool { if m == nil || m.ExcludeAttachments == nil { return false } return *m.ExcludeAttachments } // GetGUID returns the GUID field if it's non-nil, zero value otherwise. func (m *Migration) GetGUID() string { if m == nil || m.GUID == nil { return "" } return *m.GUID } // GetID returns the ID field if it's non-nil, zero value otherwise. func (m *Migration) GetID() int64 { if m == nil || m.ID == nil { return 0 } return *m.ID } // GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. func (m *Migration) GetLockRepositories() bool { if m == nil || m.LockRepositories == nil { return false } return *m.LockRepositories } // GetState returns the State field if it's non-nil, zero value otherwise. func (m *Migration) GetState() string { if m == nil || m.State == nil { return "" } return *m.State } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (m *Migration) GetUpdatedAt() string { if m == nil || m.UpdatedAt == nil { return "" } return *m.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (m *Migration) GetURL() string { if m == nil || m.URL == nil { return "" } return *m.URL } // GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. func (m *Milestone) GetClosedAt() time.Time { if m == nil || m.ClosedAt == nil { return time.Time{} } return *m.ClosedAt } // GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. func (m *Milestone) GetClosedIssues() int { if m == nil || m.ClosedIssues == nil { return 0 } return *m.ClosedIssues } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (m *Milestone) GetCreatedAt() time.Time { if m == nil || m.CreatedAt == nil { return time.Time{} } return *m.CreatedAt } // GetCreator returns the Creator field. func (m *Milestone) GetCreator() *User { if m == nil { return nil } return m.Creator } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (m *Milestone) GetDescription() string { if m == nil || m.Description == nil { return "" } return *m.Description } // GetDueOn returns the DueOn field if it's non-nil, zero value otherwise. func (m *Milestone) GetDueOn() time.Time { if m == nil || m.DueOn == nil { return time.Time{} } return *m.DueOn } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (m *Milestone) GetHTMLURL() string { if m == nil || m.HTMLURL == nil { return "" } return *m.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (m *Milestone) GetID() int64 { if m == nil || m.ID == nil { return 0 } return *m.ID } // GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. func (m *Milestone) GetLabelsURL() string { if m == nil || m.LabelsURL == nil { return "" } return *m.LabelsURL } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (m *Milestone) GetNodeID() string { if m == nil || m.NodeID == nil { return "" } return *m.NodeID } // GetNumber returns the Number field if it's non-nil, zero value otherwise. func (m *Milestone) GetNumber() int { if m == nil || m.Number == nil { return 0 } return *m.Number } // GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. func (m *Milestone) GetOpenIssues() int { if m == nil || m.OpenIssues == nil { return 0 } return *m.OpenIssues } // GetState returns the State field if it's non-nil, zero value otherwise. func (m *Milestone) GetState() string { if m == nil || m.State == nil { return "" } return *m.State } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (m *Milestone) GetTitle() string { if m == nil || m.Title == nil { return "" } return *m.Title } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (m *Milestone) GetUpdatedAt() time.Time { if m == nil || m.UpdatedAt == nil { return time.Time{} } return *m.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (m *Milestone) GetURL() string { if m == nil || m.URL == nil { return "" } return *m.URL } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (m *MilestoneEvent) GetAction() string { if m == nil || m.Action == nil { return "" } return *m.Action } // GetChanges returns the Changes field. func (m *MilestoneEvent) GetChanges() *EditChange { if m == nil { return nil } return m.Changes } // GetInstallation returns the Installation field. func (m *MilestoneEvent) GetInstallation() *Installation { if m == nil { return nil } return m.Installation } // GetMilestone returns the Milestone field. func (m *MilestoneEvent) GetMilestone() *Milestone { if m == nil { return nil } return m.Milestone } // GetOrg returns the Org field. func (m *MilestoneEvent) GetOrg() *Organization { if m == nil { return nil } return m.Org } // GetRepo returns the Repo field. func (m *MilestoneEvent) GetRepo() *Repository { if m == nil { return nil } return m.Repo } // GetSender returns the Sender field. func (m *MilestoneEvent) GetSender() *User { if m == nil { return nil } return m.Sender } // GetClosedMilestones returns the ClosedMilestones field if it's non-nil, zero value otherwise. func (m *MilestoneStats) GetClosedMilestones() int { if m == nil || m.ClosedMilestones == nil { return 0 } return *m.ClosedMilestones } // GetOpenMilestones returns the OpenMilestones field if it's non-nil, zero value otherwise. func (m *MilestoneStats) GetOpenMilestones() int { if m == nil || m.OpenMilestones == nil { return 0 } return *m.OpenMilestones } // GetTotalMilestones returns the TotalMilestones field if it's non-nil, zero value otherwise. func (m *MilestoneStats) GetTotalMilestones() int { if m == nil || m.TotalMilestones == nil { return 0 } return *m.TotalMilestones } // GetBase returns the Base field if it's non-nil, zero value otherwise. func (n *NewPullRequest) GetBase() string { if n == nil || n.Base == nil { return "" } return *n.Base } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (n *NewPullRequest) GetBody() string { if n == nil || n.Body == nil { return "" } return *n.Body } // GetDraft returns the Draft field if it's non-nil, zero value otherwise. func (n *NewPullRequest) GetDraft() bool { if n == nil || n.Draft == nil { return false } return *n.Draft } // GetHead returns the Head field if it's non-nil, zero value otherwise. func (n *NewPullRequest) GetHead() string { if n == nil || n.Head == nil { return "" } return *n.Head } // GetIssue returns the Issue field if it's non-nil, zero value otherwise. func (n *NewPullRequest) GetIssue() int { if n == nil || n.Issue == nil { return 0 } return *n.Issue } // GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. func (n *NewPullRequest) GetMaintainerCanModify() bool { if n == nil || n.MaintainerCanModify == nil { return false } return *n.MaintainerCanModify } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (n *NewPullRequest) GetTitle() string { if n == nil || n.Title == nil { return "" } return *n.Title } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (n *NewTeam) GetDescription() string { if n == nil || n.Description == nil { return "" } return *n.Description } // GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. func (n *NewTeam) GetLDAPDN() string { if n == nil || n.LDAPDN == nil { return "" } return *n.LDAPDN } // GetParentTeamID returns the ParentTeamID field if it's non-nil, zero value otherwise. func (n *NewTeam) GetParentTeamID() int64 { if n == nil || n.ParentTeamID == nil { return 0 } return *n.ParentTeamID } // GetPermission returns the Permission field if it's non-nil, zero value otherwise. func (n *NewTeam) GetPermission() string { if n == nil || n.Permission == nil { return "" } return *n.Permission } // GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. func (n *NewTeam) GetPrivacy() string { if n == nil || n.Privacy == nil { return "" } return *n.Privacy } // GetID returns the ID field if it's non-nil, zero value otherwise. func (n *Notification) GetID() string { if n == nil || n.ID == nil { return "" } return *n.ID } // GetLastReadAt returns the LastReadAt field if it's non-nil, zero value otherwise. func (n *Notification) GetLastReadAt() time.Time { if n == nil || n.LastReadAt == nil { return time.Time{} } return *n.LastReadAt } // GetReason returns the Reason field if it's non-nil, zero value otherwise. func (n *Notification) GetReason() string { if n == nil || n.Reason == nil { return "" } return *n.Reason } // GetRepository returns the Repository field. func (n *Notification) GetRepository() *Repository { if n == nil { return nil } return n.Repository } // GetSubject returns the Subject field. func (n *Notification) GetSubject() *NotificationSubject { if n == nil { return nil } return n.Subject } // GetUnread returns the Unread field if it's non-nil, zero value otherwise. func (n *Notification) GetUnread() bool { if n == nil || n.Unread == nil { return false } return *n.Unread } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (n *Notification) GetUpdatedAt() time.Time { if n == nil || n.UpdatedAt == nil { return time.Time{} } return *n.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (n *Notification) GetURL() string { if n == nil || n.URL == nil { return "" } return *n.URL } // GetLatestCommentURL returns the LatestCommentURL field if it's non-nil, zero value otherwise. func (n *NotificationSubject) GetLatestCommentURL() string { if n == nil || n.LatestCommentURL == nil { return "" } return *n.LatestCommentURL } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (n *NotificationSubject) GetTitle() string { if n == nil || n.Title == nil { return "" } return *n.Title } // GetType returns the Type field if it's non-nil, zero value otherwise. func (n *NotificationSubject) GetType() string { if n == nil || n.Type == nil { return "" } return *n.Type } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (n *NotificationSubject) GetURL() string { if n == nil || n.URL == nil { return "" } return *n.URL } // GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. func (o *Organization) GetAvatarURL() string { if o == nil || o.AvatarURL == nil { return "" } return *o.AvatarURL } // GetBillingEmail returns the BillingEmail field if it's non-nil, zero value otherwise. func (o *Organization) GetBillingEmail() string { if o == nil || o.BillingEmail == nil { return "" } return *o.BillingEmail } // GetBlog returns the Blog field if it's non-nil, zero value otherwise. func (o *Organization) GetBlog() string { if o == nil || o.Blog == nil { return "" } return *o.Blog } // GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. func (o *Organization) GetCollaborators() int { if o == nil || o.Collaborators == nil { return 0 } return *o.Collaborators } // GetCompany returns the Company field if it's non-nil, zero value otherwise. func (o *Organization) GetCompany() string { if o == nil || o.Company == nil { return "" } return *o.Company } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (o *Organization) GetCreatedAt() time.Time { if o == nil || o.CreatedAt == nil { return time.Time{} } return *o.CreatedAt } // GetDefaultRepoPermission returns the DefaultRepoPermission field if it's non-nil, zero value otherwise. func (o *Organization) GetDefaultRepoPermission() string { if o == nil || o.DefaultRepoPermission == nil { return "" } return *o.DefaultRepoPermission } // GetDefaultRepoSettings returns the DefaultRepoSettings field if it's non-nil, zero value otherwise. func (o *Organization) GetDefaultRepoSettings() string { if o == nil || o.DefaultRepoSettings == nil { return "" } return *o.DefaultRepoSettings } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (o *Organization) GetDescription() string { if o == nil || o.Description == nil { return "" } return *o.Description } // GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. func (o *Organization) GetDiskUsage() int { if o == nil || o.DiskUsage == nil { return 0 } return *o.DiskUsage } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (o *Organization) GetEmail() string { if o == nil || o.Email == nil { return "" } return *o.Email } // GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. func (o *Organization) GetEventsURL() string { if o == nil || o.EventsURL == nil { return "" } return *o.EventsURL } // GetFollowers returns the Followers field if it's non-nil, zero value otherwise. func (o *Organization) GetFollowers() int { if o == nil || o.Followers == nil { return 0 } return *o.Followers } // GetFollowing returns the Following field if it's non-nil, zero value otherwise. func (o *Organization) GetFollowing() int { if o == nil || o.Following == nil { return 0 } return *o.Following } // GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. func (o *Organization) GetHooksURL() string { if o == nil || o.HooksURL == nil { return "" } return *o.HooksURL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (o *Organization) GetHTMLURL() string { if o == nil || o.HTMLURL == nil { return "" } return *o.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (o *Organization) GetID() int64 { if o == nil || o.ID == nil { return 0 } return *o.ID } // GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. func (o *Organization) GetIssuesURL() string { if o == nil || o.IssuesURL == nil { return "" } return *o.IssuesURL } // GetLocation returns the Location field if it's non-nil, zero value otherwise. func (o *Organization) GetLocation() string { if o == nil || o.Location == nil { return "" } return *o.Location } // GetLogin returns the Login field if it's non-nil, zero value otherwise. func (o *Organization) GetLogin() string { if o == nil || o.Login == nil { return "" } return *o.Login } // GetMembersAllowedRepositoryCreationType returns the MembersAllowedRepositoryCreationType field if it's non-nil, zero value otherwise. func (o *Organization) GetMembersAllowedRepositoryCreationType() string { if o == nil || o.MembersAllowedRepositoryCreationType == nil { return "" } return *o.MembersAllowedRepositoryCreationType } // GetMembersCanCreateRepos returns the MembersCanCreateRepos field if it's non-nil, zero value otherwise. func (o *Organization) GetMembersCanCreateRepos() bool { if o == nil || o.MembersCanCreateRepos == nil { return false } return *o.MembersCanCreateRepos } // GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. func (o *Organization) GetMembersURL() string { if o == nil || o.MembersURL == nil { return "" } return *o.MembersURL } // GetName returns the Name field if it's non-nil, zero value otherwise. func (o *Organization) GetName() string { if o == nil || o.Name == nil { return "" } return *o.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (o *Organization) GetNodeID() string { if o == nil || o.NodeID == nil { return "" } return *o.NodeID } // GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. func (o *Organization) GetOwnedPrivateRepos() int { if o == nil || o.OwnedPrivateRepos == nil { return 0 } return *o.OwnedPrivateRepos } // GetPlan returns the Plan field. func (o *Organization) GetPlan() *Plan { if o == nil { return nil } return o.Plan } // GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. func (o *Organization) GetPrivateGists() int { if o == nil || o.PrivateGists == nil { return 0 } return *o.PrivateGists } // GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. func (o *Organization) GetPublicGists() int { if o == nil || o.PublicGists == nil { return 0 } return *o.PublicGists } // GetPublicMembersURL returns the PublicMembersURL field if it's non-nil, zero value otherwise. func (o *Organization) GetPublicMembersURL() string { if o == nil || o.PublicMembersURL == nil { return "" } return *o.PublicMembersURL } // GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. func (o *Organization) GetPublicRepos() int { if o == nil || o.PublicRepos == nil { return 0 } return *o.PublicRepos } // GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. func (o *Organization) GetReposURL() string { if o == nil || o.ReposURL == nil { return "" } return *o.ReposURL } // GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. func (o *Organization) GetTotalPrivateRepos() int { if o == nil || o.TotalPrivateRepos == nil { return 0 } return *o.TotalPrivateRepos } // GetTwoFactorRequirementEnabled returns the TwoFactorRequirementEnabled field if it's non-nil, zero value otherwise. func (o *Organization) GetTwoFactorRequirementEnabled() bool { if o == nil || o.TwoFactorRequirementEnabled == nil { return false } return *o.TwoFactorRequirementEnabled } // GetType returns the Type field if it's non-nil, zero value otherwise. func (o *Organization) GetType() string { if o == nil || o.Type == nil { return "" } return *o.Type } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (o *Organization) GetUpdatedAt() time.Time { if o == nil || o.UpdatedAt == nil { return time.Time{} } return *o.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (o *Organization) GetURL() string { if o == nil || o.URL == nil { return "" } return *o.URL } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (o *OrganizationEvent) GetAction() string { if o == nil || o.Action == nil { return "" } return *o.Action } // GetInstallation returns the Installation field. func (o *OrganizationEvent) GetInstallation() *Installation { if o == nil { return nil } return o.Installation } // GetInvitation returns the Invitation field. func (o *OrganizationEvent) GetInvitation() *Invitation { if o == nil { return nil } return o.Invitation } // GetMembership returns the Membership field. func (o *OrganizationEvent) GetMembership() *Membership { if o == nil { return nil } return o.Membership } // GetOrganization returns the Organization field. func (o *OrganizationEvent) GetOrganization() *Organization { if o == nil { return nil } return o.Organization } // GetSender returns the Sender field. func (o *OrganizationEvent) GetSender() *User { if o == nil { return nil } return o.Sender } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (o *OrgBlockEvent) GetAction() string { if o == nil || o.Action == nil { return "" } return *o.Action } // GetBlockedUser returns the BlockedUser field. func (o *OrgBlockEvent) GetBlockedUser() *User { if o == nil { return nil } return o.BlockedUser } // GetInstallation returns the Installation field. func (o *OrgBlockEvent) GetInstallation() *Installation { if o == nil { return nil } return o.Installation } // GetOrganization returns the Organization field. func (o *OrgBlockEvent) GetOrganization() *Organization { if o == nil { return nil } return o.Organization } // GetSender returns the Sender field. func (o *OrgBlockEvent) GetSender() *User { if o == nil { return nil } return o.Sender } // GetDisabledOrgs returns the DisabledOrgs field if it's non-nil, zero value otherwise. func (o *OrgStats) GetDisabledOrgs() int { if o == nil || o.DisabledOrgs == nil { return 0 } return *o.DisabledOrgs } // GetTotalOrgs returns the TotalOrgs field if it's non-nil, zero value otherwise. func (o *OrgStats) GetTotalOrgs() int { if o == nil || o.TotalOrgs == nil { return 0 } return *o.TotalOrgs } // GetTotalTeamMembers returns the TotalTeamMembers field if it's non-nil, zero value otherwise. func (o *OrgStats) GetTotalTeamMembers() int { if o == nil || o.TotalTeamMembers == nil { return 0 } return *o.TotalTeamMembers } // GetTotalTeams returns the TotalTeams field if it's non-nil, zero value otherwise. func (o *OrgStats) GetTotalTeams() int { if o == nil || o.TotalTeams == nil { return 0 } return *o.TotalTeams } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *Page) GetAction() string { if p == nil || p.Action == nil { return "" } return *p.Action } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (p *Page) GetHTMLURL() string { if p == nil || p.HTMLURL == nil { return "" } return *p.HTMLURL } // GetPageName returns the PageName field if it's non-nil, zero value otherwise. func (p *Page) GetPageName() string { if p == nil || p.PageName == nil { return "" } return *p.PageName } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (p *Page) GetSHA() string { if p == nil || p.SHA == nil { return "" } return *p.SHA } // GetSummary returns the Summary field if it's non-nil, zero value otherwise. func (p *Page) GetSummary() string { if p == nil || p.Summary == nil { return "" } return *p.Summary } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (p *Page) GetTitle() string { if p == nil || p.Title == nil { return "" } return *p.Title } // GetBuild returns the Build field. func (p *PageBuildEvent) GetBuild() *PagesBuild { if p == nil { return nil } return p.Build } // GetID returns the ID field if it's non-nil, zero value otherwise. func (p *PageBuildEvent) GetID() int64 { if p == nil || p.ID == nil { return 0 } return *p.ID } // GetInstallation returns the Installation field. func (p *PageBuildEvent) GetInstallation() *Installation { if p == nil { return nil } return p.Installation } // GetRepo returns the Repo field. func (p *PageBuildEvent) GetRepo() *Repository { if p == nil { return nil } return p.Repo } // GetSender returns the Sender field. func (p *PageBuildEvent) GetSender() *User { if p == nil { return nil } return p.Sender } // GetCNAME returns the CNAME field if it's non-nil, zero value otherwise. func (p *Pages) GetCNAME() string { if p == nil || p.CNAME == nil { return "" } return *p.CNAME } // GetCustom404 returns the Custom404 field if it's non-nil, zero value otherwise. func (p *Pages) GetCustom404() bool { if p == nil || p.Custom404 == nil { return false } return *p.Custom404 } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (p *Pages) GetHTMLURL() string { if p == nil || p.HTMLURL == nil { return "" } return *p.HTMLURL } // GetSource returns the Source field. func (p *Pages) GetSource() *PagesSource { if p == nil { return nil } return p.Source } // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (p *Pages) GetStatus() string { if p == nil || p.Status == nil { return "" } return *p.Status } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *Pages) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetCommit returns the Commit field if it's non-nil, zero value otherwise. func (p *PagesBuild) GetCommit() string { if p == nil || p.Commit == nil { return "" } return *p.Commit } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (p *PagesBuild) GetCreatedAt() Timestamp { if p == nil || p.CreatedAt == nil { return Timestamp{} } return *p.CreatedAt } // GetDuration returns the Duration field if it's non-nil, zero value otherwise. func (p *PagesBuild) GetDuration() int { if p == nil || p.Duration == nil { return 0 } return *p.Duration } // GetError returns the Error field. func (p *PagesBuild) GetError() *PagesError { if p == nil { return nil } return p.Error } // GetPusher returns the Pusher field. func (p *PagesBuild) GetPusher() *User { if p == nil { return nil } return p.Pusher } // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (p *PagesBuild) GetStatus() string { if p == nil || p.Status == nil { return "" } return *p.Status } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (p *PagesBuild) GetUpdatedAt() Timestamp { if p == nil || p.UpdatedAt == nil { return Timestamp{} } return *p.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *PagesBuild) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (p *PagesError) GetMessage() string { if p == nil || p.Message == nil { return "" } return *p.Message } // GetBranch returns the Branch field if it's non-nil, zero value otherwise. func (p *PagesSource) GetBranch() string { if p == nil || p.Branch == nil { return "" } return *p.Branch } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (p *PagesSource) GetPath() string { if p == nil || p.Path == nil { return "" } return *p.Path } // GetTotalPages returns the TotalPages field if it's non-nil, zero value otherwise. func (p *PageStats) GetTotalPages() int { if p == nil || p.TotalPages == nil { return 0 } return *p.TotalPages } // GetHook returns the Hook field. func (p *PingEvent) GetHook() *Hook { if p == nil { return nil } return p.Hook } // GetHookID returns the HookID field if it's non-nil, zero value otherwise. func (p *PingEvent) GetHookID() int64 { if p == nil || p.HookID == nil { return 0 } return *p.HookID } // GetInstallation returns the Installation field. func (p *PingEvent) GetInstallation() *Installation { if p == nil { return nil } return p.Installation } // GetZen returns the Zen field if it's non-nil, zero value otherwise. func (p *PingEvent) GetZen() string { if p == nil || p.Zen == nil { return "" } return *p.Zen } // GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. func (p *Plan) GetCollaborators() int { if p == nil || p.Collaborators == nil { return 0 } return *p.Collaborators } // GetName returns the Name field if it's non-nil, zero value otherwise. func (p *Plan) GetName() string { if p == nil || p.Name == nil { return "" } return *p.Name } // GetPrivateRepos returns the PrivateRepos field if it's non-nil, zero value otherwise. func (p *Plan) GetPrivateRepos() int { if p == nil || p.PrivateRepos == nil { return 0 } return *p.PrivateRepos } // GetSpace returns the Space field if it's non-nil, zero value otherwise. func (p *Plan) GetSpace() int { if p == nil || p.Space == nil { return 0 } return *p.Space } // GetConfigURL returns the ConfigURL field if it's non-nil, zero value otherwise. func (p *PreReceiveHook) GetConfigURL() string { if p == nil || p.ConfigURL == nil { return "" } return *p.ConfigURL } // GetEnforcement returns the Enforcement field if it's non-nil, zero value otherwise. func (p *PreReceiveHook) GetEnforcement() string { if p == nil || p.Enforcement == nil { return "" } return *p.Enforcement } // GetID returns the ID field if it's non-nil, zero value otherwise. func (p *PreReceiveHook) GetID() int64 { if p == nil || p.ID == nil { return 0 } return *p.ID } // GetName returns the Name field if it's non-nil, zero value otherwise. func (p *PreReceiveHook) GetName() string { if p == nil || p.Name == nil { return "" } return *p.Name } // GetHRef returns the HRef field if it's non-nil, zero value otherwise. func (p *PRLink) GetHRef() string { if p == nil || p.HRef == nil { return "" } return *p.HRef } // GetComments returns the Comments field. func (p *PRLinks) GetComments() *PRLink { if p == nil { return nil } return p.Comments } // GetCommits returns the Commits field. func (p *PRLinks) GetCommits() *PRLink { if p == nil { return nil } return p.Commits } // GetHTML returns the HTML field. func (p *PRLinks) GetHTML() *PRLink { if p == nil { return nil } return p.HTML } // GetIssue returns the Issue field. func (p *PRLinks) GetIssue() *PRLink { if p == nil { return nil } return p.Issue } // GetReviewComment returns the ReviewComment field. func (p *PRLinks) GetReviewComment() *PRLink { if p == nil { return nil } return p.ReviewComment } // GetReviewComments returns the ReviewComments field. func (p *PRLinks) GetReviewComments() *PRLink { if p == nil { return nil } return p.ReviewComments } // GetSelf returns the Self field. func (p *PRLinks) GetSelf() *PRLink { if p == nil { return nil } return p.Self } // GetStatuses returns the Statuses field. func (p *PRLinks) GetStatuses() *PRLink { if p == nil { return nil } return p.Statuses } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (p *Project) GetBody() string { if p == nil || p.Body == nil { return "" } return *p.Body } // GetColumnsURL returns the ColumnsURL field if it's non-nil, zero value otherwise. func (p *Project) GetColumnsURL() string { if p == nil || p.ColumnsURL == nil { return "" } return *p.ColumnsURL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (p *Project) GetCreatedAt() Timestamp { if p == nil || p.CreatedAt == nil { return Timestamp{} } return *p.CreatedAt } // GetCreator returns the Creator field. func (p *Project) GetCreator() *User { if p == nil { return nil } return p.Creator } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (p *Project) GetHTMLURL() string { if p == nil || p.HTMLURL == nil { return "" } return *p.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (p *Project) GetID() int64 { if p == nil || p.ID == nil { return 0 } return *p.ID } // GetName returns the Name field if it's non-nil, zero value otherwise. func (p *Project) GetName() string { if p == nil || p.Name == nil { return "" } return *p.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (p *Project) GetNodeID() string { if p == nil || p.NodeID == nil { return "" } return *p.NodeID } // GetNumber returns the Number field if it's non-nil, zero value otherwise. func (p *Project) GetNumber() int { if p == nil || p.Number == nil { return 0 } return *p.Number } // GetOwnerURL returns the OwnerURL field if it's non-nil, zero value otherwise. func (p *Project) GetOwnerURL() string { if p == nil || p.OwnerURL == nil { return "" } return *p.OwnerURL } // GetState returns the State field if it's non-nil, zero value otherwise. func (p *Project) GetState() string { if p == nil || p.State == nil { return "" } return *p.State } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (p *Project) GetUpdatedAt() Timestamp { if p == nil || p.UpdatedAt == nil { return Timestamp{} } return *p.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *Project) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetArchived returns the Archived field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetArchived() bool { if p == nil || p.Archived == nil { return false } return *p.Archived } // GetColumnID returns the ColumnID field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetColumnID() int64 { if p == nil || p.ColumnID == nil { return 0 } return *p.ColumnID } // GetColumnName returns the ColumnName field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetColumnName() string { if p == nil || p.ColumnName == nil { return "" } return *p.ColumnName } // GetColumnURL returns the ColumnURL field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetColumnURL() string { if p == nil || p.ColumnURL == nil { return "" } return *p.ColumnURL } // GetContentURL returns the ContentURL field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetContentURL() string { if p == nil || p.ContentURL == nil { return "" } return *p.ContentURL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetCreatedAt() Timestamp { if p == nil || p.CreatedAt == nil { return Timestamp{} } return *p.CreatedAt } // GetCreator returns the Creator field. func (p *ProjectCard) GetCreator() *User { if p == nil { return nil } return p.Creator } // GetID returns the ID field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetID() int64 { if p == nil || p.ID == nil { return 0 } return *p.ID } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetNodeID() string { if p == nil || p.NodeID == nil { return "" } return *p.NodeID } // GetNote returns the Note field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetNote() string { if p == nil || p.Note == nil { return "" } return *p.Note } // GetPreviousColumnName returns the PreviousColumnName field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetPreviousColumnName() string { if p == nil || p.PreviousColumnName == nil { return "" } return *p.PreviousColumnName } // GetProjectID returns the ProjectID field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetProjectID() int64 { if p == nil || p.ProjectID == nil { return 0 } return *p.ProjectID } // GetProjectURL returns the ProjectURL field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetProjectURL() string { if p == nil || p.ProjectURL == nil { return "" } return *p.ProjectURL } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetUpdatedAt() Timestamp { if p == nil || p.UpdatedAt == nil { return Timestamp{} } return *p.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *ProjectCardEvent) GetAction() string { if p == nil || p.Action == nil { return "" } return *p.Action } // GetAfterID returns the AfterID field if it's non-nil, zero value otherwise. func (p *ProjectCardEvent) GetAfterID() int64 { if p == nil || p.AfterID == nil { return 0 } return *p.AfterID } // GetChanges returns the Changes field. func (p *ProjectCardEvent) GetChanges() *ProjectCardChange { if p == nil { return nil } return p.Changes } // GetInstallation returns the Installation field. func (p *ProjectCardEvent) GetInstallation() *Installation { if p == nil { return nil } return p.Installation } // GetOrg returns the Org field. func (p *ProjectCardEvent) GetOrg() *Organization { if p == nil { return nil } return p.Org } // GetProjectCard returns the ProjectCard field. func (p *ProjectCardEvent) GetProjectCard() *ProjectCard { if p == nil { return nil } return p.ProjectCard } // GetRepo returns the Repo field. func (p *ProjectCardEvent) GetRepo() *Repository { if p == nil { return nil } return p.Repo } // GetSender returns the Sender field. func (p *ProjectCardEvent) GetSender() *User { if p == nil { return nil } return p.Sender } // GetArchivedState returns the ArchivedState field if it's non-nil, zero value otherwise. func (p *ProjectCardListOptions) GetArchivedState() string { if p == nil || p.ArchivedState == nil { return "" } return *p.ArchivedState } // GetArchived returns the Archived field if it's non-nil, zero value otherwise. func (p *ProjectCardOptions) GetArchived() bool { if p == nil || p.Archived == nil { return false } return *p.Archived } // GetPermission returns the Permission field if it's non-nil, zero value otherwise. func (p *ProjectCollaboratorOptions) GetPermission() string { if p == nil || p.Permission == nil { return "" } return *p.Permission } // GetCardsURL returns the CardsURL field if it's non-nil, zero value otherwise. func (p *ProjectColumn) GetCardsURL() string { if p == nil || p.CardsURL == nil { return "" } return *p.CardsURL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (p *ProjectColumn) GetCreatedAt() Timestamp { if p == nil || p.CreatedAt == nil { return Timestamp{} } return *p.CreatedAt } // GetID returns the ID field if it's non-nil, zero value otherwise. func (p *ProjectColumn) GetID() int64 { if p == nil || p.ID == nil { return 0 } return *p.ID } // GetName returns the Name field if it's non-nil, zero value otherwise. func (p *ProjectColumn) GetName() string { if p == nil || p.Name == nil { return "" } return *p.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (p *ProjectColumn) GetNodeID() string { if p == nil || p.NodeID == nil { return "" } return *p.NodeID } // GetProjectURL returns the ProjectURL field if it's non-nil, zero value otherwise. func (p *ProjectColumn) GetProjectURL() string { if p == nil || p.ProjectURL == nil { return "" } return *p.ProjectURL } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (p *ProjectColumn) GetUpdatedAt() Timestamp { if p == nil || p.UpdatedAt == nil { return Timestamp{} } return *p.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *ProjectColumn) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *ProjectColumnEvent) GetAction() string { if p == nil || p.Action == nil { return "" } return *p.Action } // GetAfterID returns the AfterID field if it's non-nil, zero value otherwise. func (p *ProjectColumnEvent) GetAfterID() int64 { if p == nil || p.AfterID == nil { return 0 } return *p.AfterID } // GetChanges returns the Changes field. func (p *ProjectColumnEvent) GetChanges() *ProjectColumnChange { if p == nil { return nil } return p.Changes } // GetInstallation returns the Installation field. func (p *ProjectColumnEvent) GetInstallation() *Installation { if p == nil { return nil } return p.Installation } // GetOrg returns the Org field. func (p *ProjectColumnEvent) GetOrg() *Organization { if p == nil { return nil } return p.Org } // GetProjectColumn returns the ProjectColumn field. func (p *ProjectColumnEvent) GetProjectColumn() *ProjectColumn { if p == nil { return nil } return p.ProjectColumn } // GetRepo returns the Repo field. func (p *ProjectColumnEvent) GetRepo() *Repository { if p == nil { return nil } return p.Repo } // GetSender returns the Sender field. func (p *ProjectColumnEvent) GetSender() *User { if p == nil { return nil } return p.Sender } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *ProjectEvent) GetAction() string { if p == nil || p.Action == nil { return "" } return *p.Action } // GetChanges returns the Changes field. func (p *ProjectEvent) GetChanges() *ProjectChange { if p == nil { return nil } return p.Changes } // GetInstallation returns the Installation field. func (p *ProjectEvent) GetInstallation() *Installation { if p == nil { return nil } return p.Installation } // GetOrg returns the Org field. func (p *ProjectEvent) GetOrg() *Organization { if p == nil { return nil } return p.Org } // GetProject returns the Project field. func (p *ProjectEvent) GetProject() *Project { if p == nil { return nil } return p.Project } // GetRepo returns the Repo field. func (p *ProjectEvent) GetRepo() *Repository { if p == nil { return nil } return p.Repo } // GetSender returns the Sender field. func (p *ProjectEvent) GetSender() *User { if p == nil { return nil } return p.Sender } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (p *ProjectOptions) GetBody() string { if p == nil || p.Body == nil { return "" } return *p.Body } // GetName returns the Name field if it's non-nil, zero value otherwise. func (p *ProjectOptions) GetName() string { if p == nil || p.Name == nil { return "" } return *p.Name } // GetOrganizationPermission returns the OrganizationPermission field if it's non-nil, zero value otherwise. func (p *ProjectOptions) GetOrganizationPermission() string { if p == nil || p.OrganizationPermission == nil { return "" } return *p.OrganizationPermission } // GetPublic returns the Public field if it's non-nil, zero value otherwise. func (p *ProjectOptions) GetPublic() bool { if p == nil || p.Public == nil { return false } return *p.Public } // GetState returns the State field if it's non-nil, zero value otherwise. func (p *ProjectOptions) GetState() string { if p == nil || p.State == nil { return "" } return *p.State } // GetPermission returns the Permission field if it's non-nil, zero value otherwise. func (p *ProjectPermissionLevel) GetPermission() string { if p == nil || p.Permission == nil { return "" } return *p.Permission } // GetUser returns the User field. func (p *ProjectPermissionLevel) GetUser() *User { if p == nil { return nil } return p.User } // GetEnforceAdmins returns the EnforceAdmins field. func (p *Protection) GetEnforceAdmins() *AdminEnforcement { if p == nil { return nil } return p.EnforceAdmins } // GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. func (p *Protection) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcement { if p == nil { return nil } return p.RequiredPullRequestReviews } // GetRequiredStatusChecks returns the RequiredStatusChecks field. func (p *Protection) GetRequiredStatusChecks() *RequiredStatusChecks { if p == nil { return nil } return p.RequiredStatusChecks } // GetRestrictions returns the Restrictions field. func (p *Protection) GetRestrictions() *BranchRestrictions { if p == nil { return nil } return p.Restrictions } // GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. func (p *ProtectionRequest) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcementRequest { if p == nil { return nil } return p.RequiredPullRequestReviews } // GetRequiredStatusChecks returns the RequiredStatusChecks field. func (p *ProtectionRequest) GetRequiredStatusChecks() *RequiredStatusChecks { if p == nil { return nil } return p.RequiredStatusChecks } // GetRestrictions returns the Restrictions field. func (p *ProtectionRequest) GetRestrictions() *BranchRestrictionsRequest { if p == nil { return nil } return p.Restrictions } // GetInstallation returns the Installation field. func (p *PublicEvent) GetInstallation() *Installation { if p == nil { return nil } return p.Installation } // GetRepo returns the Repo field. func (p *PublicEvent) GetRepo() *Repository { if p == nil { return nil } return p.Repo } // GetSender returns the Sender field. func (p *PublicEvent) GetSender() *User { if p == nil { return nil } return p.Sender } // GetExpectedHeadSHA returns the ExpectedHeadSHA field if it's non-nil, zero value otherwise. func (p *PullReqestBranchUpdateOptions) GetExpectedHeadSHA() string { if p == nil || p.ExpectedHeadSHA == nil { return "" } return *p.ExpectedHeadSHA } // GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. func (p *PullRequest) GetActiveLockReason() string { if p == nil || p.ActiveLockReason == nil { return "" } return *p.ActiveLockReason } // GetAdditions returns the Additions field if it's non-nil, zero value otherwise. func (p *PullRequest) GetAdditions() int { if p == nil || p.Additions == nil { return 0 } return *p.Additions } // GetAssignee returns the Assignee field. func (p *PullRequest) GetAssignee() *User { if p == nil { return nil } return p.Assignee } // GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. func (p *PullRequest) GetAuthorAssociation() string { if p == nil || p.AuthorAssociation == nil { return "" } return *p.AuthorAssociation } // GetBase returns the Base field. func (p *PullRequest) GetBase() *PullRequestBranch { if p == nil { return nil } return p.Base } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (p *PullRequest) GetBody() string { if p == nil || p.Body == nil { return "" } return *p.Body } // GetChangedFiles returns the ChangedFiles field if it's non-nil, zero value otherwise. func (p *PullRequest) GetChangedFiles() int { if p == nil || p.ChangedFiles == nil { return 0 } return *p.ChangedFiles } // GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. func (p *PullRequest) GetClosedAt() time.Time { if p == nil || p.ClosedAt == nil { return time.Time{} } return *p.ClosedAt } // GetComments returns the Comments field if it's non-nil, zero value otherwise. func (p *PullRequest) GetComments() int { if p == nil || p.Comments == nil { return 0 } return *p.Comments } // GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. func (p *PullRequest) GetCommentsURL() string { if p == nil || p.CommentsURL == nil { return "" } return *p.CommentsURL } // GetCommits returns the Commits field if it's non-nil, zero value otherwise. func (p *PullRequest) GetCommits() int { if p == nil || p.Commits == nil { return 0 } return *p.Commits } // GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. func (p *PullRequest) GetCommitsURL() string { if p == nil || p.CommitsURL == nil { return "" } return *p.CommitsURL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (p *PullRequest) GetCreatedAt() time.Time { if p == nil || p.CreatedAt == nil { return time.Time{} } return *p.CreatedAt } // GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. func (p *PullRequest) GetDeletions() int { if p == nil || p.Deletions == nil { return 0 } return *p.Deletions } // GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. func (p *PullRequest) GetDiffURL() string { if p == nil || p.DiffURL == nil { return "" } return *p.DiffURL } // GetDraft returns the Draft field if it's non-nil, zero value otherwise. func (p *PullRequest) GetDraft() bool { if p == nil || p.Draft == nil { return false } return *p.Draft } // GetHead returns the Head field. func (p *PullRequest) GetHead() *PullRequestBranch { if p == nil { return nil } return p.Head } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (p *PullRequest) GetHTMLURL() string { if p == nil || p.HTMLURL == nil { return "" } return *p.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (p *PullRequest) GetID() int64 { if p == nil || p.ID == nil { return 0 } return *p.ID } // GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. func (p *PullRequest) GetIssueURL() string { if p == nil || p.IssueURL == nil { return "" } return *p.IssueURL } // GetLinks returns the Links field. func (p *PullRequest) GetLinks() *PRLinks { if p == nil { return nil } return p.Links } // GetLocked returns the Locked field if it's non-nil, zero value otherwise. func (p *PullRequest) GetLocked() bool { if p == nil || p.Locked == nil { return false } return *p.Locked } // GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. func (p *PullRequest) GetMaintainerCanModify() bool { if p == nil || p.MaintainerCanModify == nil { return false } return *p.MaintainerCanModify } // GetMergeable returns the Mergeable field if it's non-nil, zero value otherwise. func (p *PullRequest) GetMergeable() bool { if p == nil || p.Mergeable == nil { return false } return *p.Mergeable } // GetMergeableState returns the MergeableState field if it's non-nil, zero value otherwise. func (p *PullRequest) GetMergeableState() string { if p == nil || p.MergeableState == nil { return "" } return *p.MergeableState } // GetMergeCommitSHA returns the MergeCommitSHA field if it's non-nil, zero value otherwise. func (p *PullRequest) GetMergeCommitSHA() string { if p == nil || p.MergeCommitSHA == nil { return "" } return *p.MergeCommitSHA } // GetMerged returns the Merged field if it's non-nil, zero value otherwise. func (p *PullRequest) GetMerged() bool { if p == nil || p.Merged == nil { return false } return *p.Merged } // GetMergedAt returns the MergedAt field if it's non-nil, zero value otherwise. func (p *PullRequest) GetMergedAt() time.Time { if p == nil || p.MergedAt == nil { return time.Time{} } return *p.MergedAt } // GetMergedBy returns the MergedBy field. func (p *PullRequest) GetMergedBy() *User { if p == nil { return nil } return p.MergedBy } // GetMilestone returns the Milestone field. func (p *PullRequest) GetMilestone() *Milestone { if p == nil { return nil } return p.Milestone } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (p *PullRequest) GetNodeID() string { if p == nil || p.NodeID == nil { return "" } return *p.NodeID } // GetNumber returns the Number field if it's non-nil, zero value otherwise. func (p *PullRequest) GetNumber() int { if p == nil || p.Number == nil { return 0 } return *p.Number } // GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. func (p *PullRequest) GetPatchURL() string { if p == nil || p.PatchURL == nil { return "" } return *p.PatchURL } // GetRebaseable returns the Rebaseable field if it's non-nil, zero value otherwise. func (p *PullRequest) GetRebaseable() bool { if p == nil || p.Rebaseable == nil { return false } return *p.Rebaseable } // GetReviewComments returns the ReviewComments field if it's non-nil, zero value otherwise. func (p *PullRequest) GetReviewComments() int { if p == nil || p.ReviewComments == nil { return 0 } return *p.ReviewComments } // GetReviewCommentsURL returns the ReviewCommentsURL field if it's non-nil, zero value otherwise. func (p *PullRequest) GetReviewCommentsURL() string { if p == nil || p.ReviewCommentsURL == nil { return "" } return *p.ReviewCommentsURL } // GetReviewCommentURL returns the ReviewCommentURL field if it's non-nil, zero value otherwise. func (p *PullRequest) GetReviewCommentURL() string { if p == nil || p.ReviewCommentURL == nil { return "" } return *p.ReviewCommentURL } // GetState returns the State field if it's non-nil, zero value otherwise. func (p *PullRequest) GetState() string { if p == nil || p.State == nil { return "" } return *p.State } // GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. func (p *PullRequest) GetStatusesURL() string { if p == nil || p.StatusesURL == nil { return "" } return *p.StatusesURL } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (p *PullRequest) GetTitle() string { if p == nil || p.Title == nil { return "" } return *p.Title } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (p *PullRequest) GetUpdatedAt() time.Time { if p == nil || p.UpdatedAt == nil { return time.Time{} } return *p.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *PullRequest) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetUser returns the User field. func (p *PullRequest) GetUser() *User { if p == nil { return nil } return p.User } // GetLabel returns the Label field if it's non-nil, zero value otherwise. func (p *PullRequestBranch) GetLabel() string { if p == nil || p.Label == nil { return "" } return *p.Label } // GetRef returns the Ref field if it's non-nil, zero value otherwise. func (p *PullRequestBranch) GetRef() string { if p == nil || p.Ref == nil { return "" } return *p.Ref } // GetRepo returns the Repo field. func (p *PullRequestBranch) GetRepo() *Repository { if p == nil { return nil } return p.Repo } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (p *PullRequestBranch) GetSHA() string { if p == nil || p.SHA == nil { return "" } return *p.SHA } // GetUser returns the User field. func (p *PullRequestBranch) GetUser() *User { if p == nil { return nil } return p.User } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (p *PullRequestBranchUpdateResponse) GetMessage() string { if p == nil || p.Message == nil { return "" } return *p.Message } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *PullRequestBranchUpdateResponse) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetAuthorAssociation() string { if p == nil || p.AuthorAssociation == nil { return "" } return *p.AuthorAssociation } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetBody() string { if p == nil || p.Body == nil { return "" } return *p.Body } // GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetCommitID() string { if p == nil || p.CommitID == nil { return "" } return *p.CommitID } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetCreatedAt() time.Time { if p == nil || p.CreatedAt == nil { return time.Time{} } return *p.CreatedAt } // GetDiffHunk returns the DiffHunk field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetDiffHunk() string { if p == nil || p.DiffHunk == nil { return "" } return *p.DiffHunk } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetHTMLURL() string { if p == nil || p.HTMLURL == nil { return "" } return *p.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetID() int64 { if p == nil || p.ID == nil { return 0 } return *p.ID } // GetInReplyTo returns the InReplyTo field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetInReplyTo() int64 { if p == nil || p.InReplyTo == nil { return 0 } return *p.InReplyTo } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetNodeID() string { if p == nil || p.NodeID == nil { return "" } return *p.NodeID } // GetOriginalCommitID returns the OriginalCommitID field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetOriginalCommitID() string { if p == nil || p.OriginalCommitID == nil { return "" } return *p.OriginalCommitID } // GetOriginalPosition returns the OriginalPosition field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetOriginalPosition() int { if p == nil || p.OriginalPosition == nil { return 0 } return *p.OriginalPosition } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetPath() string { if p == nil || p.Path == nil { return "" } return *p.Path } // GetPosition returns the Position field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetPosition() int { if p == nil || p.Position == nil { return 0 } return *p.Position } // GetPullRequestReviewID returns the PullRequestReviewID field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetPullRequestReviewID() int64 { if p == nil || p.PullRequestReviewID == nil { return 0 } return *p.PullRequestReviewID } // GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetPullRequestURL() string { if p == nil || p.PullRequestURL == nil { return "" } return *p.PullRequestURL } // GetReactions returns the Reactions field. func (p *PullRequestComment) GetReactions() *Reactions { if p == nil { return nil } return p.Reactions } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetUpdatedAt() time.Time { if p == nil || p.UpdatedAt == nil { return time.Time{} } return *p.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *PullRequestComment) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetUser returns the User field. func (p *PullRequestComment) GetUser() *User { if p == nil { return nil } return p.User } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *PullRequestEvent) GetAction() string { if p == nil || p.Action == nil { return "" } return *p.Action } // GetAssignee returns the Assignee field. func (p *PullRequestEvent) GetAssignee() *User { if p == nil { return nil } return p.Assignee } // GetChanges returns the Changes field. func (p *PullRequestEvent) GetChanges() *EditChange { if p == nil { return nil } return p.Changes } // GetInstallation returns the Installation field. func (p *PullRequestEvent) GetInstallation() *Installation { if p == nil { return nil } return p.Installation } // GetLabel returns the Label field. func (p *PullRequestEvent) GetLabel() *Label { if p == nil { return nil } return p.Label } // GetNumber returns the Number field if it's non-nil, zero value otherwise. func (p *PullRequestEvent) GetNumber() int { if p == nil || p.Number == nil { return 0 } return *p.Number } // GetOrganization returns the Organization field. func (p *PullRequestEvent) GetOrganization() *Organization { if p == nil { return nil } return p.Organization } // GetPullRequest returns the PullRequest field. func (p *PullRequestEvent) GetPullRequest() *PullRequest { if p == nil { return nil } return p.PullRequest } // GetRepo returns the Repo field. func (p *PullRequestEvent) GetRepo() *Repository { if p == nil { return nil } return p.Repo } // GetRequestedReviewer returns the RequestedReviewer field. func (p *PullRequestEvent) GetRequestedReviewer() *User { if p == nil { return nil } return p.RequestedReviewer } // GetRequestedTeam returns the RequestedTeam field. func (p *PullRequestEvent) GetRequestedTeam() *Team { if p == nil { return nil } return p.RequestedTeam } // GetSender returns the Sender field. func (p *PullRequestEvent) GetSender() *User { if p == nil { return nil } return p.Sender } // GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. func (p *PullRequestLinks) GetDiffURL() string { if p == nil || p.DiffURL == nil { return "" } return *p.DiffURL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (p *PullRequestLinks) GetHTMLURL() string { if p == nil || p.HTMLURL == nil { return "" } return *p.HTMLURL } // GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. func (p *PullRequestLinks) GetPatchURL() string { if p == nil || p.PatchURL == nil { return "" } return *p.PatchURL } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *PullRequestLinks) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetMerged returns the Merged field if it's non-nil, zero value otherwise. func (p *PullRequestMergeResult) GetMerged() bool { if p == nil || p.Merged == nil { return false } return *p.Merged } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (p *PullRequestMergeResult) GetMessage() string { if p == nil || p.Message == nil { return "" } return *p.Message } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (p *PullRequestMergeResult) GetSHA() string { if p == nil || p.SHA == nil { return "" } return *p.SHA } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (p *PullRequestReview) GetBody() string { if p == nil || p.Body == nil { return "" } return *p.Body } // GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. func (p *PullRequestReview) GetCommitID() string { if p == nil || p.CommitID == nil { return "" } return *p.CommitID } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (p *PullRequestReview) GetHTMLURL() string { if p == nil || p.HTMLURL == nil { return "" } return *p.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (p *PullRequestReview) GetID() int64 { if p == nil || p.ID == nil { return 0 } return *p.ID } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (p *PullRequestReview) GetNodeID() string { if p == nil || p.NodeID == nil { return "" } return *p.NodeID } // GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. func (p *PullRequestReview) GetPullRequestURL() string { if p == nil || p.PullRequestURL == nil { return "" } return *p.PullRequestURL } // GetState returns the State field if it's non-nil, zero value otherwise. func (p *PullRequestReview) GetState() string { if p == nil || p.State == nil { return "" } return *p.State } // GetSubmittedAt returns the SubmittedAt field if it's non-nil, zero value otherwise. func (p *PullRequestReview) GetSubmittedAt() time.Time { if p == nil || p.SubmittedAt == nil { return time.Time{} } return *p.SubmittedAt } // GetUser returns the User field. func (p *PullRequestReview) GetUser() *User { if p == nil { return nil } return p.User } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *PullRequestReviewCommentEvent) GetAction() string { if p == nil || p.Action == nil { return "" } return *p.Action } // GetChanges returns the Changes field. func (p *PullRequestReviewCommentEvent) GetChanges() *EditChange { if p == nil { return nil } return p.Changes } // GetComment returns the Comment field. func (p *PullRequestReviewCommentEvent) GetComment() *PullRequestComment { if p == nil { return nil } return p.Comment } // GetInstallation returns the Installation field. func (p *PullRequestReviewCommentEvent) GetInstallation() *Installation { if p == nil { return nil } return p.Installation } // GetPullRequest returns the PullRequest field. func (p *PullRequestReviewCommentEvent) GetPullRequest() *PullRequest { if p == nil { return nil } return p.PullRequest } // GetRepo returns the Repo field. func (p *PullRequestReviewCommentEvent) GetRepo() *Repository { if p == nil { return nil } return p.Repo } // GetSender returns the Sender field. func (p *PullRequestReviewCommentEvent) GetSender() *User { if p == nil { return nil } return p.Sender } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (p *PullRequestReviewDismissalRequest) GetMessage() string { if p == nil || p.Message == nil { return "" } return *p.Message } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *PullRequestReviewEvent) GetAction() string { if p == nil || p.Action == nil { return "" } return *p.Action } // GetInstallation returns the Installation field. func (p *PullRequestReviewEvent) GetInstallation() *Installation { if p == nil { return nil } return p.Installation } // GetOrganization returns the Organization field. func (p *PullRequestReviewEvent) GetOrganization() *Organization { if p == nil { return nil } return p.Organization } // GetPullRequest returns the PullRequest field. func (p *PullRequestReviewEvent) GetPullRequest() *PullRequest { if p == nil { return nil } return p.PullRequest } // GetRepo returns the Repo field. func (p *PullRequestReviewEvent) GetRepo() *Repository { if p == nil { return nil } return p.Repo } // GetReview returns the Review field. func (p *PullRequestReviewEvent) GetReview() *PullRequestReview { if p == nil { return nil } return p.Review } // GetSender returns the Sender field. func (p *PullRequestReviewEvent) GetSender() *User { if p == nil { return nil } return p.Sender } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (p *PullRequestReviewRequest) GetBody() string { if p == nil || p.Body == nil { return "" } return *p.Body } // GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. func (p *PullRequestReviewRequest) GetCommitID() string { if p == nil || p.CommitID == nil { return "" } return *p.CommitID } // GetEvent returns the Event field if it's non-nil, zero value otherwise. func (p *PullRequestReviewRequest) GetEvent() string { if p == nil || p.Event == nil { return "" } return *p.Event } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (p *PullRequestReviewRequest) GetNodeID() string { if p == nil || p.NodeID == nil { return "" } return *p.NodeID } // GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. func (p *PullRequestReviewsEnforcementRequest) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { if p == nil { return nil } return p.DismissalRestrictionsRequest } // GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. func (p *PullRequestReviewsEnforcementUpdate) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { if p == nil { return nil } return p.DismissalRestrictionsRequest } // GetDismissStaleReviews returns the DismissStaleReviews field if it's non-nil, zero value otherwise. func (p *PullRequestReviewsEnforcementUpdate) GetDismissStaleReviews() bool { if p == nil || p.DismissStaleReviews == nil { return false } return *p.DismissStaleReviews } // GetMergablePulls returns the MergablePulls field if it's non-nil, zero value otherwise. func (p *PullStats) GetMergablePulls() int { if p == nil || p.MergablePulls == nil { return 0 } return *p.MergablePulls } // GetMergedPulls returns the MergedPulls field if it's non-nil, zero value otherwise. func (p *PullStats) GetMergedPulls() int { if p == nil || p.MergedPulls == nil { return 0 } return *p.MergedPulls } // GetTotalPulls returns the TotalPulls field if it's non-nil, zero value otherwise. func (p *PullStats) GetTotalPulls() int { if p == nil || p.TotalPulls == nil { return 0 } return *p.TotalPulls } // GetUnmergablePulls returns the UnmergablePulls field if it's non-nil, zero value otherwise. func (p *PullStats) GetUnmergablePulls() int { if p == nil || p.UnmergablePulls == nil { return 0 } return *p.UnmergablePulls } // GetCommits returns the Commits field if it's non-nil, zero value otherwise. func (p *PunchCard) GetCommits() int { if p == nil || p.Commits == nil { return 0 } return *p.Commits } // GetDay returns the Day field if it's non-nil, zero value otherwise. func (p *PunchCard) GetDay() int { if p == nil || p.Day == nil { return 0 } return *p.Day } // GetHour returns the Hour field if it's non-nil, zero value otherwise. func (p *PunchCard) GetHour() int { if p == nil || p.Hour == nil { return 0 } return *p.Hour } // GetAfter returns the After field if it's non-nil, zero value otherwise. func (p *PushEvent) GetAfter() string { if p == nil || p.After == nil { return "" } return *p.After } // GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise. func (p *PushEvent) GetBaseRef() string { if p == nil || p.BaseRef == nil { return "" } return *p.BaseRef } // GetBefore returns the Before field if it's non-nil, zero value otherwise. func (p *PushEvent) GetBefore() string { if p == nil || p.Before == nil { return "" } return *p.Before } // GetCompare returns the Compare field if it's non-nil, zero value otherwise. func (p *PushEvent) GetCompare() string { if p == nil || p.Compare == nil { return "" } return *p.Compare } // GetCreated returns the Created field if it's non-nil, zero value otherwise. func (p *PushEvent) GetCreated() bool { if p == nil || p.Created == nil { return false } return *p.Created } // GetDeleted returns the Deleted field if it's non-nil, zero value otherwise. func (p *PushEvent) GetDeleted() bool { if p == nil || p.Deleted == nil { return false } return *p.Deleted } // GetDistinctSize returns the DistinctSize field if it's non-nil, zero value otherwise. func (p *PushEvent) GetDistinctSize() int { if p == nil || p.DistinctSize == nil { return 0 } return *p.DistinctSize } // GetForced returns the Forced field if it's non-nil, zero value otherwise. func (p *PushEvent) GetForced() bool { if p == nil || p.Forced == nil { return false } return *p.Forced } // GetHead returns the Head field if it's non-nil, zero value otherwise. func (p *PushEvent) GetHead() string { if p == nil || p.Head == nil { return "" } return *p.Head } // GetHeadCommit returns the HeadCommit field. func (p *PushEvent) GetHeadCommit() *PushEventCommit { if p == nil { return nil } return p.HeadCommit } // GetInstallation returns the Installation field. func (p *PushEvent) GetInstallation() *Installation { if p == nil { return nil } return p.Installation } // GetPusher returns the Pusher field. func (p *PushEvent) GetPusher() *User { if p == nil { return nil } return p.Pusher } // GetPushID returns the PushID field if it's non-nil, zero value otherwise. func (p *PushEvent) GetPushID() int64 { if p == nil || p.PushID == nil { return 0 } return *p.PushID } // GetRef returns the Ref field if it's non-nil, zero value otherwise. func (p *PushEvent) GetRef() string { if p == nil || p.Ref == nil { return "" } return *p.Ref } // GetRepo returns the Repo field. func (p *PushEvent) GetRepo() *PushEventRepository { if p == nil { return nil } return p.Repo } // GetSender returns the Sender field. func (p *PushEvent) GetSender() *User { if p == nil { return nil } return p.Sender } // GetSize returns the Size field if it's non-nil, zero value otherwise. func (p *PushEvent) GetSize() int { if p == nil || p.Size == nil { return 0 } return *p.Size } // GetAuthor returns the Author field. func (p *PushEventCommit) GetAuthor() *CommitAuthor { if p == nil { return nil } return p.Author } // GetCommitter returns the Committer field. func (p *PushEventCommit) GetCommitter() *CommitAuthor { if p == nil { return nil } return p.Committer } // GetDistinct returns the Distinct field if it's non-nil, zero value otherwise. func (p *PushEventCommit) GetDistinct() bool { if p == nil || p.Distinct == nil { return false } return *p.Distinct } // GetID returns the ID field if it's non-nil, zero value otherwise. func (p *PushEventCommit) GetID() string { if p == nil || p.ID == nil { return "" } return *p.ID } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (p *PushEventCommit) GetMessage() string { if p == nil || p.Message == nil { return "" } return *p.Message } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (p *PushEventCommit) GetSHA() string { if p == nil || p.SHA == nil { return "" } return *p.SHA } // GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. func (p *PushEventCommit) GetTimestamp() Timestamp { if p == nil || p.Timestamp == nil { return Timestamp{} } return *p.Timestamp } // GetTreeID returns the TreeID field if it's non-nil, zero value otherwise. func (p *PushEventCommit) GetTreeID() string { if p == nil || p.TreeID == nil { return "" } return *p.TreeID } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *PushEventCommit) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (p *PushEventRepoOwner) GetEmail() string { if p == nil || p.Email == nil { return "" } return *p.Email } // GetName returns the Name field if it's non-nil, zero value otherwise. func (p *PushEventRepoOwner) GetName() string { if p == nil || p.Name == nil { return "" } return *p.Name } // GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetArchiveURL() string { if p == nil || p.ArchiveURL == nil { return "" } return *p.ArchiveURL } // GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetCloneURL() string { if p == nil || p.CloneURL == nil { return "" } return *p.CloneURL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetCreatedAt() Timestamp { if p == nil || p.CreatedAt == nil { return Timestamp{} } return *p.CreatedAt } // GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetDefaultBranch() string { if p == nil || p.DefaultBranch == nil { return "" } return *p.DefaultBranch } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetDescription() string { if p == nil || p.Description == nil { return "" } return *p.Description } // GetFork returns the Fork field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetFork() bool { if p == nil || p.Fork == nil { return false } return *p.Fork } // GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetForksCount() int { if p == nil || p.ForksCount == nil { return 0 } return *p.ForksCount } // GetFullName returns the FullName field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetFullName() string { if p == nil || p.FullName == nil { return "" } return *p.FullName } // GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetGitURL() string { if p == nil || p.GitURL == nil { return "" } return *p.GitURL } // GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetHasDownloads() bool { if p == nil || p.HasDownloads == nil { return false } return *p.HasDownloads } // GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetHasIssues() bool { if p == nil || p.HasIssues == nil { return false } return *p.HasIssues } // GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetHasPages() bool { if p == nil || p.HasPages == nil { return false } return *p.HasPages } // GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetHasWiki() bool { if p == nil || p.HasWiki == nil { return false } return *p.HasWiki } // GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetHomepage() string { if p == nil || p.Homepage == nil { return "" } return *p.Homepage } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetHTMLURL() string { if p == nil || p.HTMLURL == nil { return "" } return *p.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetID() int64 { if p == nil || p.ID == nil { return 0 } return *p.ID } // GetLanguage returns the Language field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetLanguage() string { if p == nil || p.Language == nil { return "" } return *p.Language } // GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetMasterBranch() string { if p == nil || p.MasterBranch == nil { return "" } return *p.MasterBranch } // GetName returns the Name field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetName() string { if p == nil || p.Name == nil { return "" } return *p.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetNodeID() string { if p == nil || p.NodeID == nil { return "" } return *p.NodeID } // GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetOpenIssuesCount() int { if p == nil || p.OpenIssuesCount == nil { return 0 } return *p.OpenIssuesCount } // GetOrganization returns the Organization field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetOrganization() string { if p == nil || p.Organization == nil { return "" } return *p.Organization } // GetOwner returns the Owner field. func (p *PushEventRepository) GetOwner() *User { if p == nil { return nil } return p.Owner } // GetPrivate returns the Private field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetPrivate() bool { if p == nil || p.Private == nil { return false } return *p.Private } // GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetPullsURL() string { if p == nil || p.PullsURL == nil { return "" } return *p.PullsURL } // GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetPushedAt() Timestamp { if p == nil || p.PushedAt == nil { return Timestamp{} } return *p.PushedAt } // GetSize returns the Size field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetSize() int { if p == nil || p.Size == nil { return 0 } return *p.Size } // GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetSSHURL() string { if p == nil || p.SSHURL == nil { return "" } return *p.SSHURL } // GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetStargazersCount() int { if p == nil || p.StargazersCount == nil { return 0 } return *p.StargazersCount } // GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetStatusesURL() string { if p == nil || p.StatusesURL == nil { return "" } return *p.StatusesURL } // GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetSVNURL() string { if p == nil || p.SVNURL == nil { return "" } return *p.SVNURL } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetUpdatedAt() Timestamp { if p == nil || p.UpdatedAt == nil { return Timestamp{} } return *p.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetURL() string { if p == nil || p.URL == nil { return "" } return *p.URL } // GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. func (p *PushEventRepository) GetWatchersCount() int { if p == nil || p.WatchersCount == nil { return 0 } return *p.WatchersCount } // GetCore returns the Core field. func (r *RateLimits) GetCore() *Rate { if r == nil { return nil } return r.Core } // GetSearch returns the Search field. func (r *RateLimits) GetSearch() *Rate { if r == nil { return nil } return r.Search } // GetContent returns the Content field if it's non-nil, zero value otherwise. func (r *Reaction) GetContent() string { if r == nil || r.Content == nil { return "" } return *r.Content } // GetID returns the ID field if it's non-nil, zero value otherwise. func (r *Reaction) GetID() int64 { if r == nil || r.ID == nil { return 0 } return *r.ID } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (r *Reaction) GetNodeID() string { if r == nil || r.NodeID == nil { return "" } return *r.NodeID } // GetUser returns the User field. func (r *Reaction) GetUser() *User { if r == nil { return nil } return r.User } // GetConfused returns the Confused field if it's non-nil, zero value otherwise. func (r *Reactions) GetConfused() int { if r == nil || r.Confused == nil { return 0 } return *r.Confused } // GetHeart returns the Heart field if it's non-nil, zero value otherwise. func (r *Reactions) GetHeart() int { if r == nil || r.Heart == nil { return 0 } return *r.Heart } // GetHooray returns the Hooray field if it's non-nil, zero value otherwise. func (r *Reactions) GetHooray() int { if r == nil || r.Hooray == nil { return 0 } return *r.Hooray } // GetLaugh returns the Laugh field if it's non-nil, zero value otherwise. func (r *Reactions) GetLaugh() int { if r == nil || r.Laugh == nil { return 0 } return *r.Laugh } // GetMinusOne returns the MinusOne field if it's non-nil, zero value otherwise. func (r *Reactions) GetMinusOne() int { if r == nil || r.MinusOne == nil { return 0 } return *r.MinusOne } // GetPlusOne returns the PlusOne field if it's non-nil, zero value otherwise. func (r *Reactions) GetPlusOne() int { if r == nil || r.PlusOne == nil { return 0 } return *r.PlusOne } // GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. func (r *Reactions) GetTotalCount() int { if r == nil || r.TotalCount == nil { return 0 } return *r.TotalCount } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *Reactions) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (r *Reference) GetNodeID() string { if r == nil || r.NodeID == nil { return "" } return *r.NodeID } // GetObject returns the Object field. func (r *Reference) GetObject() *GitObject { if r == nil { return nil } return r.Object } // GetRef returns the Ref field if it's non-nil, zero value otherwise. func (r *Reference) GetRef() string { if r == nil || r.Ref == nil { return "" } return *r.Ref } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *Reference) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetBrowserDownloadURL returns the BrowserDownloadURL field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetBrowserDownloadURL() string { if r == nil || r.BrowserDownloadURL == nil { return "" } return *r.BrowserDownloadURL } // GetContentType returns the ContentType field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetContentType() string { if r == nil || r.ContentType == nil { return "" } return *r.ContentType } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetCreatedAt() Timestamp { if r == nil || r.CreatedAt == nil { return Timestamp{} } return *r.CreatedAt } // GetDownloadCount returns the DownloadCount field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetDownloadCount() int { if r == nil || r.DownloadCount == nil { return 0 } return *r.DownloadCount } // GetID returns the ID field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetID() int64 { if r == nil || r.ID == nil { return 0 } return *r.ID } // GetLabel returns the Label field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetLabel() string { if r == nil || r.Label == nil { return "" } return *r.Label } // GetName returns the Name field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetName() string { if r == nil || r.Name == nil { return "" } return *r.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetNodeID() string { if r == nil || r.NodeID == nil { return "" } return *r.NodeID } // GetSize returns the Size field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetSize() int { if r == nil || r.Size == nil { return 0 } return *r.Size } // GetState returns the State field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetState() string { if r == nil || r.State == nil { return "" } return *r.State } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetUpdatedAt() Timestamp { if r == nil || r.UpdatedAt == nil { return Timestamp{} } return *r.UpdatedAt } // GetUploader returns the Uploader field. func (r *ReleaseAsset) GetUploader() *User { if r == nil { return nil } return r.Uploader } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *ReleaseAsset) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (r *ReleaseEvent) GetAction() string { if r == nil || r.Action == nil { return "" } return *r.Action } // GetInstallation returns the Installation field. func (r *ReleaseEvent) GetInstallation() *Installation { if r == nil { return nil } return r.Installation } // GetRelease returns the Release field. func (r *ReleaseEvent) GetRelease() *RepositoryRelease { if r == nil { return nil } return r.Release } // GetRepo returns the Repo field. func (r *ReleaseEvent) GetRepo() *Repository { if r == nil { return nil } return r.Repo } // GetSender returns the Sender field. func (r *ReleaseEvent) GetSender() *User { if r == nil { return nil } return r.Sender } // GetFrom returns the From field if it's non-nil, zero value otherwise. func (r *Rename) GetFrom() string { if r == nil || r.From == nil { return "" } return *r.From } // GetTo returns the To field if it's non-nil, zero value otherwise. func (r *Rename) GetTo() string { if r == nil || r.To == nil { return "" } return *r.To } // GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. func (r *RepositoriesSearchResult) GetIncompleteResults() bool { if r == nil || r.IncompleteResults == nil { return false } return *r.IncompleteResults } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (r *RepositoriesSearchResult) GetTotal() int { if r == nil || r.Total == nil { return 0 } return *r.Total } // GetAllowMergeCommit returns the AllowMergeCommit field if it's non-nil, zero value otherwise. func (r *Repository) GetAllowMergeCommit() bool { if r == nil || r.AllowMergeCommit == nil { return false } return *r.AllowMergeCommit } // GetAllowRebaseMerge returns the AllowRebaseMerge field if it's non-nil, zero value otherwise. func (r *Repository) GetAllowRebaseMerge() bool { if r == nil || r.AllowRebaseMerge == nil { return false } return *r.AllowRebaseMerge } // GetAllowSquashMerge returns the AllowSquashMerge field if it's non-nil, zero value otherwise. func (r *Repository) GetAllowSquashMerge() bool { if r == nil || r.AllowSquashMerge == nil { return false } return *r.AllowSquashMerge } // GetArchived returns the Archived field if it's non-nil, zero value otherwise. func (r *Repository) GetArchived() bool { if r == nil || r.Archived == nil { return false } return *r.Archived } // GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. func (r *Repository) GetArchiveURL() string { if r == nil || r.ArchiveURL == nil { return "" } return *r.ArchiveURL } // GetAssigneesURL returns the AssigneesURL field if it's non-nil, zero value otherwise. func (r *Repository) GetAssigneesURL() string { if r == nil || r.AssigneesURL == nil { return "" } return *r.AssigneesURL } // GetAutoInit returns the AutoInit field if it's non-nil, zero value otherwise. func (r *Repository) GetAutoInit() bool { if r == nil || r.AutoInit == nil { return false } return *r.AutoInit } // GetBlobsURL returns the BlobsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetBlobsURL() string { if r == nil || r.BlobsURL == nil { return "" } return *r.BlobsURL } // GetBranchesURL returns the BranchesURL field if it's non-nil, zero value otherwise. func (r *Repository) GetBranchesURL() string { if r == nil || r.BranchesURL == nil { return "" } return *r.BranchesURL } // GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. func (r *Repository) GetCloneURL() string { if r == nil || r.CloneURL == nil { return "" } return *r.CloneURL } // GetCodeOfConduct returns the CodeOfConduct field. func (r *Repository) GetCodeOfConduct() *CodeOfConduct { if r == nil { return nil } return r.CodeOfConduct } // GetCollaboratorsURL returns the CollaboratorsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetCollaboratorsURL() string { if r == nil || r.CollaboratorsURL == nil { return "" } return *r.CollaboratorsURL } // GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetCommentsURL() string { if r == nil || r.CommentsURL == nil { return "" } return *r.CommentsURL } // GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetCommitsURL() string { if r == nil || r.CommitsURL == nil { return "" } return *r.CommitsURL } // GetCompareURL returns the CompareURL field if it's non-nil, zero value otherwise. func (r *Repository) GetCompareURL() string { if r == nil || r.CompareURL == nil { return "" } return *r.CompareURL } // GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetContentsURL() string { if r == nil || r.ContentsURL == nil { return "" } return *r.ContentsURL } // GetContributorsURL returns the ContributorsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetContributorsURL() string { if r == nil || r.ContributorsURL == nil { return "" } return *r.ContributorsURL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (r *Repository) GetCreatedAt() Timestamp { if r == nil || r.CreatedAt == nil { return Timestamp{} } return *r.CreatedAt } // GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. func (r *Repository) GetDefaultBranch() string { if r == nil || r.DefaultBranch == nil { return "" } return *r.DefaultBranch } // GetDeploymentsURL returns the DeploymentsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetDeploymentsURL() string { if r == nil || r.DeploymentsURL == nil { return "" } return *r.DeploymentsURL } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (r *Repository) GetDescription() string { if r == nil || r.Description == nil { return "" } return *r.Description } // GetDisabled returns the Disabled field if it's non-nil, zero value otherwise. func (r *Repository) GetDisabled() bool { if r == nil || r.Disabled == nil { return false } return *r.Disabled } // GetDownloadsURL returns the DownloadsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetDownloadsURL() string { if r == nil || r.DownloadsURL == nil { return "" } return *r.DownloadsURL } // GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetEventsURL() string { if r == nil || r.EventsURL == nil { return "" } return *r.EventsURL } // GetFork returns the Fork field if it's non-nil, zero value otherwise. func (r *Repository) GetFork() bool { if r == nil || r.Fork == nil { return false } return *r.Fork } // GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. func (r *Repository) GetForksCount() int { if r == nil || r.ForksCount == nil { return 0 } return *r.ForksCount } // GetForksURL returns the ForksURL field if it's non-nil, zero value otherwise. func (r *Repository) GetForksURL() string { if r == nil || r.ForksURL == nil { return "" } return *r.ForksURL } // GetFullName returns the FullName field if it's non-nil, zero value otherwise. func (r *Repository) GetFullName() string { if r == nil || r.FullName == nil { return "" } return *r.FullName } // GetGitCommitsURL returns the GitCommitsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetGitCommitsURL() string { if r == nil || r.GitCommitsURL == nil { return "" } return *r.GitCommitsURL } // GetGitignoreTemplate returns the GitignoreTemplate field if it's non-nil, zero value otherwise. func (r *Repository) GetGitignoreTemplate() string { if r == nil || r.GitignoreTemplate == nil { return "" } return *r.GitignoreTemplate } // GetGitRefsURL returns the GitRefsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetGitRefsURL() string { if r == nil || r.GitRefsURL == nil { return "" } return *r.GitRefsURL } // GetGitTagsURL returns the GitTagsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetGitTagsURL() string { if r == nil || r.GitTagsURL == nil { return "" } return *r.GitTagsURL } // GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. func (r *Repository) GetGitURL() string { if r == nil || r.GitURL == nil { return "" } return *r.GitURL } // GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. func (r *Repository) GetHasDownloads() bool { if r == nil || r.HasDownloads == nil { return false } return *r.HasDownloads } // GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. func (r *Repository) GetHasIssues() bool { if r == nil || r.HasIssues == nil { return false } return *r.HasIssues } // GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. func (r *Repository) GetHasPages() bool { if r == nil || r.HasPages == nil { return false } return *r.HasPages } // GetHasProjects returns the HasProjects field if it's non-nil, zero value otherwise. func (r *Repository) GetHasProjects() bool { if r == nil || r.HasProjects == nil { return false } return *r.HasProjects } // GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. func (r *Repository) GetHasWiki() bool { if r == nil || r.HasWiki == nil { return false } return *r.HasWiki } // GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. func (r *Repository) GetHomepage() string { if r == nil || r.Homepage == nil { return "" } return *r.Homepage } // GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. func (r *Repository) GetHooksURL() string { if r == nil || r.HooksURL == nil { return "" } return *r.HooksURL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (r *Repository) GetHTMLURL() string { if r == nil || r.HTMLURL == nil { return "" } return *r.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (r *Repository) GetID() int64 { if r == nil || r.ID == nil { return 0 } return *r.ID } // GetIssueCommentURL returns the IssueCommentURL field if it's non-nil, zero value otherwise. func (r *Repository) GetIssueCommentURL() string { if r == nil || r.IssueCommentURL == nil { return "" } return *r.IssueCommentURL } // GetIssueEventsURL returns the IssueEventsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetIssueEventsURL() string { if r == nil || r.IssueEventsURL == nil { return "" } return *r.IssueEventsURL } // GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. func (r *Repository) GetIssuesURL() string { if r == nil || r.IssuesURL == nil { return "" } return *r.IssuesURL } // GetIsTemplate returns the IsTemplate field if it's non-nil, zero value otherwise. func (r *Repository) GetIsTemplate() bool { if r == nil || r.IsTemplate == nil { return false } return *r.IsTemplate } // GetKeysURL returns the KeysURL field if it's non-nil, zero value otherwise. func (r *Repository) GetKeysURL() string { if r == nil || r.KeysURL == nil { return "" } return *r.KeysURL } // GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetLabelsURL() string { if r == nil || r.LabelsURL == nil { return "" } return *r.LabelsURL } // GetLanguage returns the Language field if it's non-nil, zero value otherwise. func (r *Repository) GetLanguage() string { if r == nil || r.Language == nil { return "" } return *r.Language } // GetLanguagesURL returns the LanguagesURL field if it's non-nil, zero value otherwise. func (r *Repository) GetLanguagesURL() string { if r == nil || r.LanguagesURL == nil { return "" } return *r.LanguagesURL } // GetLicense returns the License field. func (r *Repository) GetLicense() *License { if r == nil { return nil } return r.License } // GetLicenseTemplate returns the LicenseTemplate field if it's non-nil, zero value otherwise. func (r *Repository) GetLicenseTemplate() string { if r == nil || r.LicenseTemplate == nil { return "" } return *r.LicenseTemplate } // GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. func (r *Repository) GetMasterBranch() string { if r == nil || r.MasterBranch == nil { return "" } return *r.MasterBranch } // GetMergesURL returns the MergesURL field if it's non-nil, zero value otherwise. func (r *Repository) GetMergesURL() string { if r == nil || r.MergesURL == nil { return "" } return *r.MergesURL } // GetMilestonesURL returns the MilestonesURL field if it's non-nil, zero value otherwise. func (r *Repository) GetMilestonesURL() string { if r == nil || r.MilestonesURL == nil { return "" } return *r.MilestonesURL } // GetMirrorURL returns the MirrorURL field if it's non-nil, zero value otherwise. func (r *Repository) GetMirrorURL() string { if r == nil || r.MirrorURL == nil { return "" } return *r.MirrorURL } // GetName returns the Name field if it's non-nil, zero value otherwise. func (r *Repository) GetName() string { if r == nil || r.Name == nil { return "" } return *r.Name } // GetNetworkCount returns the NetworkCount field if it's non-nil, zero value otherwise. func (r *Repository) GetNetworkCount() int { if r == nil || r.NetworkCount == nil { return 0 } return *r.NetworkCount } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (r *Repository) GetNodeID() string { if r == nil || r.NodeID == nil { return "" } return *r.NodeID } // GetNotificationsURL returns the NotificationsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetNotificationsURL() string { if r == nil || r.NotificationsURL == nil { return "" } return *r.NotificationsURL } // GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. func (r *Repository) GetOpenIssuesCount() int { if r == nil || r.OpenIssuesCount == nil { return 0 } return *r.OpenIssuesCount } // GetOrganization returns the Organization field. func (r *Repository) GetOrganization() *Organization { if r == nil { return nil } return r.Organization } // GetOwner returns the Owner field. func (r *Repository) GetOwner() *User { if r == nil { return nil } return r.Owner } // GetParent returns the Parent field. func (r *Repository) GetParent() *Repository { if r == nil { return nil } return r.Parent } // GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. func (r *Repository) GetPermissions() map[string]bool { if r == nil || r.Permissions == nil { return map[string]bool{} } return *r.Permissions } // GetPrivate returns the Private field if it's non-nil, zero value otherwise. func (r *Repository) GetPrivate() bool { if r == nil || r.Private == nil { return false } return *r.Private } // GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetPullsURL() string { if r == nil || r.PullsURL == nil { return "" } return *r.PullsURL } // GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. func (r *Repository) GetPushedAt() Timestamp { if r == nil || r.PushedAt == nil { return Timestamp{} } return *r.PushedAt } // GetReleasesURL returns the ReleasesURL field if it's non-nil, zero value otherwise. func (r *Repository) GetReleasesURL() string { if r == nil || r.ReleasesURL == nil { return "" } return *r.ReleasesURL } // GetSize returns the Size field if it's non-nil, zero value otherwise. func (r *Repository) GetSize() int { if r == nil || r.Size == nil { return 0 } return *r.Size } // GetSource returns the Source field. func (r *Repository) GetSource() *Repository { if r == nil { return nil } return r.Source } // GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. func (r *Repository) GetSSHURL() string { if r == nil || r.SSHURL == nil { return "" } return *r.SSHURL } // GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. func (r *Repository) GetStargazersCount() int { if r == nil || r.StargazersCount == nil { return 0 } return *r.StargazersCount } // GetStargazersURL returns the StargazersURL field if it's non-nil, zero value otherwise. func (r *Repository) GetStargazersURL() string { if r == nil || r.StargazersURL == nil { return "" } return *r.StargazersURL } // GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. func (r *Repository) GetStatusesURL() string { if r == nil || r.StatusesURL == nil { return "" } return *r.StatusesURL } // GetSubscribersCount returns the SubscribersCount field if it's non-nil, zero value otherwise. func (r *Repository) GetSubscribersCount() int { if r == nil || r.SubscribersCount == nil { return 0 } return *r.SubscribersCount } // GetSubscribersURL returns the SubscribersURL field if it's non-nil, zero value otherwise. func (r *Repository) GetSubscribersURL() string { if r == nil || r.SubscribersURL == nil { return "" } return *r.SubscribersURL } // GetSubscriptionURL returns the SubscriptionURL field if it's non-nil, zero value otherwise. func (r *Repository) GetSubscriptionURL() string { if r == nil || r.SubscriptionURL == nil { return "" } return *r.SubscriptionURL } // GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. func (r *Repository) GetSVNURL() string { if r == nil || r.SVNURL == nil { return "" } return *r.SVNURL } // GetTagsURL returns the TagsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetTagsURL() string { if r == nil || r.TagsURL == nil { return "" } return *r.TagsURL } // GetTeamID returns the TeamID field if it's non-nil, zero value otherwise. func (r *Repository) GetTeamID() int64 { if r == nil || r.TeamID == nil { return 0 } return *r.TeamID } // GetTeamsURL returns the TeamsURL field if it's non-nil, zero value otherwise. func (r *Repository) GetTeamsURL() string { if r == nil || r.TeamsURL == nil { return "" } return *r.TeamsURL } // GetTemplateRepository returns the TemplateRepository field. func (r *Repository) GetTemplateRepository() *Repository { if r == nil { return nil } return r.TemplateRepository } // GetTreesURL returns the TreesURL field if it's non-nil, zero value otherwise. func (r *Repository) GetTreesURL() string { if r == nil || r.TreesURL == nil { return "" } return *r.TreesURL } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (r *Repository) GetUpdatedAt() Timestamp { if r == nil || r.UpdatedAt == nil { return Timestamp{} } return *r.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *Repository) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. func (r *Repository) GetWatchersCount() int { if r == nil || r.WatchersCount == nil { return 0 } return *r.WatchersCount } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (r *RepositoryComment) GetBody() string { if r == nil || r.Body == nil { return "" } return *r.Body } // GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. func (r *RepositoryComment) GetCommitID() string { if r == nil || r.CommitID == nil { return "" } return *r.CommitID } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (r *RepositoryComment) GetCreatedAt() time.Time { if r == nil || r.CreatedAt == nil { return time.Time{} } return *r.CreatedAt } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (r *RepositoryComment) GetHTMLURL() string { if r == nil || r.HTMLURL == nil { return "" } return *r.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (r *RepositoryComment) GetID() int64 { if r == nil || r.ID == nil { return 0 } return *r.ID } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (r *RepositoryComment) GetNodeID() string { if r == nil || r.NodeID == nil { return "" } return *r.NodeID } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (r *RepositoryComment) GetPath() string { if r == nil || r.Path == nil { return "" } return *r.Path } // GetPosition returns the Position field if it's non-nil, zero value otherwise. func (r *RepositoryComment) GetPosition() int { if r == nil || r.Position == nil { return 0 } return *r.Position } // GetReactions returns the Reactions field. func (r *RepositoryComment) GetReactions() *Reactions { if r == nil { return nil } return r.Reactions } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (r *RepositoryComment) GetUpdatedAt() time.Time { if r == nil || r.UpdatedAt == nil { return time.Time{} } return *r.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *RepositoryComment) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetUser returns the User field. func (r *RepositoryComment) GetUser() *User { if r == nil { return nil } return r.User } // GetAuthor returns the Author field. func (r *RepositoryCommit) GetAuthor() *User { if r == nil { return nil } return r.Author } // GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. func (r *RepositoryCommit) GetCommentsURL() string { if r == nil || r.CommentsURL == nil { return "" } return *r.CommentsURL } // GetCommit returns the Commit field. func (r *RepositoryCommit) GetCommit() *Commit { if r == nil { return nil } return r.Commit } // GetCommitter returns the Committer field. func (r *RepositoryCommit) GetCommitter() *User { if r == nil { return nil } return r.Committer } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (r *RepositoryCommit) GetHTMLURL() string { if r == nil || r.HTMLURL == nil { return "" } return *r.HTMLURL } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (r *RepositoryCommit) GetNodeID() string { if r == nil || r.NodeID == nil { return "" } return *r.NodeID } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (r *RepositoryCommit) GetSHA() string { if r == nil || r.SHA == nil { return "" } return *r.SHA } // GetStats returns the Stats field. func (r *RepositoryCommit) GetStats() *CommitStats { if r == nil { return nil } return r.Stats } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *RepositoryCommit) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetDownloadURL() string { if r == nil || r.DownloadURL == nil { return "" } return *r.DownloadURL } // GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetEncoding() string { if r == nil || r.Encoding == nil { return "" } return *r.Encoding } // GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetGitURL() string { if r == nil || r.GitURL == nil { return "" } return *r.GitURL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetHTMLURL() string { if r == nil || r.HTMLURL == nil { return "" } return *r.HTMLURL } // GetName returns the Name field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetName() string { if r == nil || r.Name == nil { return "" } return *r.Name } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetPath() string { if r == nil || r.Path == nil { return "" } return *r.Path } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetSHA() string { if r == nil || r.SHA == nil { return "" } return *r.SHA } // GetSize returns the Size field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetSize() int { if r == nil || r.Size == nil { return 0 } return *r.Size } // GetTarget returns the Target field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetTarget() string { if r == nil || r.Target == nil { return "" } return *r.Target } // GetType returns the Type field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetType() string { if r == nil || r.Type == nil { return "" } return *r.Type } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *RepositoryContent) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetAuthor returns the Author field. func (r *RepositoryContentFileOptions) GetAuthor() *CommitAuthor { if r == nil { return nil } return r.Author } // GetBranch returns the Branch field if it's non-nil, zero value otherwise. func (r *RepositoryContentFileOptions) GetBranch() string { if r == nil || r.Branch == nil { return "" } return *r.Branch } // GetCommitter returns the Committer field. func (r *RepositoryContentFileOptions) GetCommitter() *CommitAuthor { if r == nil { return nil } return r.Committer } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (r *RepositoryContentFileOptions) GetMessage() string { if r == nil || r.Message == nil { return "" } return *r.Message } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (r *RepositoryContentFileOptions) GetSHA() string { if r == nil || r.SHA == nil { return "" } return *r.SHA } // GetContent returns the Content field. func (r *RepositoryContentResponse) GetContent() *RepositoryContent { if r == nil { return nil } return r.Content } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (r *RepositoryEvent) GetAction() string { if r == nil || r.Action == nil { return "" } return *r.Action } // GetInstallation returns the Installation field. func (r *RepositoryEvent) GetInstallation() *Installation { if r == nil { return nil } return r.Installation } // GetOrg returns the Org field. func (r *RepositoryEvent) GetOrg() *Organization { if r == nil { return nil } return r.Org } // GetRepo returns the Repo field. func (r *RepositoryEvent) GetRepo() *Repository { if r == nil { return nil } return r.Repo } // GetSender returns the Sender field. func (r *RepositoryEvent) GetSender() *User { if r == nil { return nil } return r.Sender } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (r *RepositoryInvitation) GetCreatedAt() Timestamp { if r == nil || r.CreatedAt == nil { return Timestamp{} } return *r.CreatedAt } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (r *RepositoryInvitation) GetHTMLURL() string { if r == nil || r.HTMLURL == nil { return "" } return *r.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (r *RepositoryInvitation) GetID() int64 { if r == nil || r.ID == nil { return 0 } return *r.ID } // GetInvitee returns the Invitee field. func (r *RepositoryInvitation) GetInvitee() *User { if r == nil { return nil } return r.Invitee } // GetInviter returns the Inviter field. func (r *RepositoryInvitation) GetInviter() *User { if r == nil { return nil } return r.Inviter } // GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. func (r *RepositoryInvitation) GetPermissions() string { if r == nil || r.Permissions == nil { return "" } return *r.Permissions } // GetRepo returns the Repo field. func (r *RepositoryInvitation) GetRepo() *Repository { if r == nil { return nil } return r.Repo } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *RepositoryInvitation) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetContent returns the Content field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetContent() string { if r == nil || r.Content == nil { return "" } return *r.Content } // GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetDownloadURL() string { if r == nil || r.DownloadURL == nil { return "" } return *r.DownloadURL } // GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetEncoding() string { if r == nil || r.Encoding == nil { return "" } return *r.Encoding } // GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetGitURL() string { if r == nil || r.GitURL == nil { return "" } return *r.GitURL } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetHTMLURL() string { if r == nil || r.HTMLURL == nil { return "" } return *r.HTMLURL } // GetLicense returns the License field. func (r *RepositoryLicense) GetLicense() *License { if r == nil { return nil } return r.License } // GetName returns the Name field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetName() string { if r == nil || r.Name == nil { return "" } return *r.Name } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetPath() string { if r == nil || r.Path == nil { return "" } return *r.Path } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetSHA() string { if r == nil || r.SHA == nil { return "" } return *r.SHA } // GetSize returns the Size field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetSize() int { if r == nil || r.Size == nil { return 0 } return *r.Size } // GetType returns the Type field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetType() string { if r == nil || r.Type == nil { return "" } return *r.Type } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *RepositoryLicense) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetBase returns the Base field if it's non-nil, zero value otherwise. func (r *RepositoryMergeRequest) GetBase() string { if r == nil || r.Base == nil { return "" } return *r.Base } // GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise. func (r *RepositoryMergeRequest) GetCommitMessage() string { if r == nil || r.CommitMessage == nil { return "" } return *r.CommitMessage } // GetHead returns the Head field if it's non-nil, zero value otherwise. func (r *RepositoryMergeRequest) GetHead() string { if r == nil || r.Head == nil { return "" } return *r.Head } // GetPermission returns the Permission field if it's non-nil, zero value otherwise. func (r *RepositoryPermissionLevel) GetPermission() string { if r == nil || r.Permission == nil { return "" } return *r.Permission } // GetUser returns the User field. func (r *RepositoryPermissionLevel) GetUser() *User { if r == nil { return nil } return r.User } // GetAssetsURL returns the AssetsURL field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetAssetsURL() string { if r == nil || r.AssetsURL == nil { return "" } return *r.AssetsURL } // GetAuthor returns the Author field. func (r *RepositoryRelease) GetAuthor() *User { if r == nil { return nil } return r.Author } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetBody() string { if r == nil || r.Body == nil { return "" } return *r.Body } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetCreatedAt() Timestamp { if r == nil || r.CreatedAt == nil { return Timestamp{} } return *r.CreatedAt } // GetDraft returns the Draft field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetDraft() bool { if r == nil || r.Draft == nil { return false } return *r.Draft } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetHTMLURL() string { if r == nil || r.HTMLURL == nil { return "" } return *r.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetID() int64 { if r == nil || r.ID == nil { return 0 } return *r.ID } // GetName returns the Name field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetName() string { if r == nil || r.Name == nil { return "" } return *r.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetNodeID() string { if r == nil || r.NodeID == nil { return "" } return *r.NodeID } // GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetPrerelease() bool { if r == nil || r.Prerelease == nil { return false } return *r.Prerelease } // GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetPublishedAt() Timestamp { if r == nil || r.PublishedAt == nil { return Timestamp{} } return *r.PublishedAt } // GetTagName returns the TagName field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetTagName() string { if r == nil || r.TagName == nil { return "" } return *r.TagName } // GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetTarballURL() string { if r == nil || r.TarballURL == nil { return "" } return *r.TarballURL } // GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetTargetCommitish() string { if r == nil || r.TargetCommitish == nil { return "" } return *r.TargetCommitish } // GetUploadURL returns the UploadURL field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetUploadURL() string { if r == nil || r.UploadURL == nil { return "" } return *r.UploadURL } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. func (r *RepositoryRelease) GetZipballURL() string { if r == nil || r.ZipballURL == nil { return "" } return *r.ZipballURL } // GetCommit returns the Commit field. func (r *RepositoryTag) GetCommit() *Commit { if r == nil { return nil } return r.Commit } // GetName returns the Name field if it's non-nil, zero value otherwise. func (r *RepositoryTag) GetName() string { if r == nil || r.Name == nil { return "" } return *r.Name } // GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. func (r *RepositoryTag) GetTarballURL() string { if r == nil || r.TarballURL == nil { return "" } return *r.TarballURL } // GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. func (r *RepositoryTag) GetZipballURL() string { if r == nil || r.ZipballURL == nil { return "" } return *r.ZipballURL } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (r *RepositoryVulnerabilityAlertEvent) GetAction() string { if r == nil || r.Action == nil { return "" } return *r.Action } // GetForkRepos returns the ForkRepos field if it's non-nil, zero value otherwise. func (r *RepoStats) GetForkRepos() int { if r == nil || r.ForkRepos == nil { return 0 } return *r.ForkRepos } // GetOrgRepos returns the OrgRepos field if it's non-nil, zero value otherwise. func (r *RepoStats) GetOrgRepos() int { if r == nil || r.OrgRepos == nil { return 0 } return *r.OrgRepos } // GetRootRepos returns the RootRepos field if it's non-nil, zero value otherwise. func (r *RepoStats) GetRootRepos() int { if r == nil || r.RootRepos == nil { return 0 } return *r.RootRepos } // GetTotalPushes returns the TotalPushes field if it's non-nil, zero value otherwise. func (r *RepoStats) GetTotalPushes() int { if r == nil || r.TotalPushes == nil { return 0 } return *r.TotalPushes } // GetTotalRepos returns the TotalRepos field if it's non-nil, zero value otherwise. func (r *RepoStats) GetTotalRepos() int { if r == nil || r.TotalRepos == nil { return 0 } return *r.TotalRepos } // GetTotalWikis returns the TotalWikis field if it's non-nil, zero value otherwise. func (r *RepoStats) GetTotalWikis() int { if r == nil || r.TotalWikis == nil { return 0 } return *r.TotalWikis } // GetContext returns the Context field if it's non-nil, zero value otherwise. func (r *RepoStatus) GetContext() string { if r == nil || r.Context == nil { return "" } return *r.Context } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (r *RepoStatus) GetCreatedAt() time.Time { if r == nil || r.CreatedAt == nil { return time.Time{} } return *r.CreatedAt } // GetCreator returns the Creator field. func (r *RepoStatus) GetCreator() *User { if r == nil { return nil } return r.Creator } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (r *RepoStatus) GetDescription() string { if r == nil || r.Description == nil { return "" } return *r.Description } // GetID returns the ID field if it's non-nil, zero value otherwise. func (r *RepoStatus) GetID() int64 { if r == nil || r.ID == nil { return 0 } return *r.ID } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (r *RepoStatus) GetNodeID() string { if r == nil || r.NodeID == nil { return "" } return *r.NodeID } // GetState returns the State field if it's non-nil, zero value otherwise. func (r *RepoStatus) GetState() string { if r == nil || r.State == nil { return "" } return *r.State } // GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. func (r *RepoStatus) GetTargetURL() string { if r == nil || r.TargetURL == nil { return "" } return *r.TargetURL } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (r *RepoStatus) GetUpdatedAt() time.Time { if r == nil || r.UpdatedAt == nil { return time.Time{} } return *r.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (r *RepoStatus) GetURL() string { if r == nil || r.URL == nil { return "" } return *r.URL } // GetStrict returns the Strict field if it's non-nil, zero value otherwise. func (r *RequiredStatusChecksRequest) GetStrict() bool { if r == nil || r.Strict == nil { return false } return *r.Strict } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (r *ReviewersRequest) GetNodeID() string { if r == nil || r.NodeID == nil { return "" } return *r.NodeID } // GetName returns the Name field if it's non-nil, zero value otherwise. func (s *ServiceHook) GetName() string { if s == nil || s.Name == nil { return "" } return *s.Name } // GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. func (s *SignaturesProtectedBranch) GetEnabled() bool { if s == nil || s.Enabled == nil { return false } return *s.Enabled } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (s *SignaturesProtectedBranch) GetURL() string { if s == nil || s.URL == nil { return "" } return *s.URL } // GetPayload returns the Payload field if it's non-nil, zero value otherwise. func (s *SignatureVerification) GetPayload() string { if s == nil || s.Payload == nil { return "" } return *s.Payload } // GetReason returns the Reason field if it's non-nil, zero value otherwise. func (s *SignatureVerification) GetReason() string { if s == nil || s.Reason == nil { return "" } return *s.Reason } // GetSignature returns the Signature field if it's non-nil, zero value otherwise. func (s *SignatureVerification) GetSignature() string { if s == nil || s.Signature == nil { return "" } return *s.Signature } // GetVerified returns the Verified field if it's non-nil, zero value otherwise. func (s *SignatureVerification) GetVerified() bool { if s == nil || s.Verified == nil { return false } return *s.Verified } // GetActor returns the Actor field. func (s *Source) GetActor() *User { if s == nil { return nil } return s.Actor } // GetID returns the ID field if it's non-nil, zero value otherwise. func (s *Source) GetID() int64 { if s == nil || s.ID == nil { return 0 } return *s.ID } // GetIssue returns the Issue field. func (s *Source) GetIssue() *Issue { if s == nil { return nil } return s.Issue } // GetType returns the Type field if it's non-nil, zero value otherwise. func (s *Source) GetType() string { if s == nil || s.Type == nil { return "" } return *s.Type } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (s *Source) GetURL() string { if s == nil || s.URL == nil { return "" } return *s.URL } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (s *SourceImportAuthor) GetEmail() string { if s == nil || s.Email == nil { return "" } return *s.Email } // GetID returns the ID field if it's non-nil, zero value otherwise. func (s *SourceImportAuthor) GetID() int64 { if s == nil || s.ID == nil { return 0 } return *s.ID } // GetImportURL returns the ImportURL field if it's non-nil, zero value otherwise. func (s *SourceImportAuthor) GetImportURL() string { if s == nil || s.ImportURL == nil { return "" } return *s.ImportURL } // GetName returns the Name field if it's non-nil, zero value otherwise. func (s *SourceImportAuthor) GetName() string { if s == nil || s.Name == nil { return "" } return *s.Name } // GetRemoteID returns the RemoteID field if it's non-nil, zero value otherwise. func (s *SourceImportAuthor) GetRemoteID() string { if s == nil || s.RemoteID == nil { return "" } return *s.RemoteID } // GetRemoteName returns the RemoteName field if it's non-nil, zero value otherwise. func (s *SourceImportAuthor) GetRemoteName() string { if s == nil || s.RemoteName == nil { return "" } return *s.RemoteName } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (s *SourceImportAuthor) GetURL() string { if s == nil || s.URL == nil { return "" } return *s.URL } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (s *StarEvent) GetAction() string { if s == nil || s.Action == nil { return "" } return *s.Action } // GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. func (s *StarEvent) GetStarredAt() Timestamp { if s == nil || s.StarredAt == nil { return Timestamp{} } return *s.StarredAt } // GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. func (s *Stargazer) GetStarredAt() Timestamp { if s == nil || s.StarredAt == nil { return Timestamp{} } return *s.StarredAt } // GetUser returns the User field. func (s *Stargazer) GetUser() *User { if s == nil { return nil } return s.User } // GetRepository returns the Repository field. func (s *StarredRepository) GetRepository() *Repository { if s == nil { return nil } return s.Repository } // GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. func (s *StarredRepository) GetStarredAt() Timestamp { if s == nil || s.StarredAt == nil { return Timestamp{} } return *s.StarredAt } // GetCommit returns the Commit field. func (s *StatusEvent) GetCommit() *RepositoryCommit { if s == nil { return nil } return s.Commit } // GetContext returns the Context field if it's non-nil, zero value otherwise. func (s *StatusEvent) GetContext() string { if s == nil || s.Context == nil { return "" } return *s.Context } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (s *StatusEvent) GetCreatedAt() Timestamp { if s == nil || s.CreatedAt == nil { return Timestamp{} } return *s.CreatedAt } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (s *StatusEvent) GetDescription() string { if s == nil || s.Description == nil { return "" } return *s.Description } // GetID returns the ID field if it's non-nil, zero value otherwise. func (s *StatusEvent) GetID() int64 { if s == nil || s.ID == nil { return 0 } return *s.ID } // GetInstallation returns the Installation field. func (s *StatusEvent) GetInstallation() *Installation { if s == nil { return nil } return s.Installation } // GetName returns the Name field if it's non-nil, zero value otherwise. func (s *StatusEvent) GetName() string { if s == nil || s.Name == nil { return "" } return *s.Name } // GetRepo returns the Repo field. func (s *StatusEvent) GetRepo() *Repository { if s == nil { return nil } return s.Repo } // GetSender returns the Sender field. func (s *StatusEvent) GetSender() *User { if s == nil { return nil } return s.Sender } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (s *StatusEvent) GetSHA() string { if s == nil || s.SHA == nil { return "" } return *s.SHA } // GetState returns the State field if it's non-nil, zero value otherwise. func (s *StatusEvent) GetState() string { if s == nil || s.State == nil { return "" } return *s.State } // GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. func (s *StatusEvent) GetTargetURL() string { if s == nil || s.TargetURL == nil { return "" } return *s.TargetURL } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (s *StatusEvent) GetUpdatedAt() Timestamp { if s == nil || s.UpdatedAt == nil { return Timestamp{} } return *s.UpdatedAt } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (s *Subscription) GetCreatedAt() Timestamp { if s == nil || s.CreatedAt == nil { return Timestamp{} } return *s.CreatedAt } // GetIgnored returns the Ignored field if it's non-nil, zero value otherwise. func (s *Subscription) GetIgnored() bool { if s == nil || s.Ignored == nil { return false } return *s.Ignored } // GetReason returns the Reason field if it's non-nil, zero value otherwise. func (s *Subscription) GetReason() string { if s == nil || s.Reason == nil { return "" } return *s.Reason } // GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. func (s *Subscription) GetRepositoryURL() string { if s == nil || s.RepositoryURL == nil { return "" } return *s.RepositoryURL } // GetSubscribed returns the Subscribed field if it's non-nil, zero value otherwise. func (s *Subscription) GetSubscribed() bool { if s == nil || s.Subscribed == nil { return false } return *s.Subscribed } // GetThreadURL returns the ThreadURL field if it's non-nil, zero value otherwise. func (s *Subscription) GetThreadURL() string { if s == nil || s.ThreadURL == nil { return "" } return *s.ThreadURL } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (s *Subscription) GetURL() string { if s == nil || s.URL == nil { return "" } return *s.URL } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (t *Tag) GetMessage() string { if t == nil || t.Message == nil { return "" } return *t.Message } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (t *Tag) GetNodeID() string { if t == nil || t.NodeID == nil { return "" } return *t.NodeID } // GetObject returns the Object field. func (t *Tag) GetObject() *GitObject { if t == nil { return nil } return t.Object } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (t *Tag) GetSHA() string { if t == nil || t.SHA == nil { return "" } return *t.SHA } // GetTag returns the Tag field if it's non-nil, zero value otherwise. func (t *Tag) GetTag() string { if t == nil || t.Tag == nil { return "" } return *t.Tag } // GetTagger returns the Tagger field. func (t *Tag) GetTagger() *CommitAuthor { if t == nil { return nil } return t.Tagger } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (t *Tag) GetURL() string { if t == nil || t.URL == nil { return "" } return *t.URL } // GetVerification returns the Verification field. func (t *Tag) GetVerification() *SignatureVerification { if t == nil { return nil } return t.Verification } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (t *Team) GetDescription() string { if t == nil || t.Description == nil { return "" } return *t.Description } // GetID returns the ID field if it's non-nil, zero value otherwise. func (t *Team) GetID() int64 { if t == nil || t.ID == nil { return 0 } return *t.ID } // GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. func (t *Team) GetLDAPDN() string { if t == nil || t.LDAPDN == nil { return "" } return *t.LDAPDN } // GetMembersCount returns the MembersCount field if it's non-nil, zero value otherwise. func (t *Team) GetMembersCount() int { if t == nil || t.MembersCount == nil { return 0 } return *t.MembersCount } // GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. func (t *Team) GetMembersURL() string { if t == nil || t.MembersURL == nil { return "" } return *t.MembersURL } // GetName returns the Name field if it's non-nil, zero value otherwise. func (t *Team) GetName() string { if t == nil || t.Name == nil { return "" } return *t.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (t *Team) GetNodeID() string { if t == nil || t.NodeID == nil { return "" } return *t.NodeID } // GetOrganization returns the Organization field. func (t *Team) GetOrganization() *Organization { if t == nil { return nil } return t.Organization } // GetParent returns the Parent field. func (t *Team) GetParent() *Team { if t == nil { return nil } return t.Parent } // GetPermission returns the Permission field if it's non-nil, zero value otherwise. func (t *Team) GetPermission() string { if t == nil || t.Permission == nil { return "" } return *t.Permission } // GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. func (t *Team) GetPrivacy() string { if t == nil || t.Privacy == nil { return "" } return *t.Privacy } // GetReposCount returns the ReposCount field if it's non-nil, zero value otherwise. func (t *Team) GetReposCount() int { if t == nil || t.ReposCount == nil { return 0 } return *t.ReposCount } // GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. func (t *Team) GetRepositoriesURL() string { if t == nil || t.RepositoriesURL == nil { return "" } return *t.RepositoriesURL } // GetSlug returns the Slug field if it's non-nil, zero value otherwise. func (t *Team) GetSlug() string { if t == nil || t.Slug == nil { return "" } return *t.Slug } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (t *Team) GetURL() string { if t == nil || t.URL == nil { return "" } return *t.URL } // GetInstallation returns the Installation field. func (t *TeamAddEvent) GetInstallation() *Installation { if t == nil { return nil } return t.Installation } // GetOrg returns the Org field. func (t *TeamAddEvent) GetOrg() *Organization { if t == nil { return nil } return t.Org } // GetRepo returns the Repo field. func (t *TeamAddEvent) GetRepo() *Repository { if t == nil { return nil } return t.Repo } // GetSender returns the Sender field. func (t *TeamAddEvent) GetSender() *User { if t == nil { return nil } return t.Sender } // GetTeam returns the Team field. func (t *TeamAddEvent) GetTeam() *Team { if t == nil { return nil } return t.Team } // GetAuthor returns the Author field. func (t *TeamDiscussion) GetAuthor() *User { if t == nil { return nil } return t.Author } // GetBody returns the Body field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetBody() string { if t == nil || t.Body == nil { return "" } return *t.Body } // GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetBodyHTML() string { if t == nil || t.BodyHTML == nil { return "" } return *t.BodyHTML } // GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetBodyVersion() string { if t == nil || t.BodyVersion == nil { return "" } return *t.BodyVersion } // GetCommentsCount returns the CommentsCount field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetCommentsCount() int { if t == nil || t.CommentsCount == nil { return 0 } return *t.CommentsCount } // GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetCommentsURL() string { if t == nil || t.CommentsURL == nil { return "" } return *t.CommentsURL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetCreatedAt() Timestamp { if t == nil || t.CreatedAt == nil { return Timestamp{} } return *t.CreatedAt } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetHTMLURL() string { if t == nil || t.HTMLURL == nil { return "" } return *t.HTMLURL } // GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetLastEditedAt() Timestamp { if t == nil || t.LastEditedAt == nil { return Timestamp{} } return *t.LastEditedAt } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetNodeID() string { if t == nil || t.NodeID == nil { return "" } return *t.NodeID } // GetNumber returns the Number field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetNumber() int { if t == nil || t.Number == nil { return 0 } return *t.Number } // GetPinned returns the Pinned field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetPinned() bool { if t == nil || t.Pinned == nil { return false } return *t.Pinned } // GetPrivate returns the Private field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetPrivate() bool { if t == nil || t.Private == nil { return false } return *t.Private } // GetReactions returns the Reactions field. func (t *TeamDiscussion) GetReactions() *Reactions { if t == nil { return nil } return t.Reactions } // GetTeamURL returns the TeamURL field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetTeamURL() string { if t == nil || t.TeamURL == nil { return "" } return *t.TeamURL } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetTitle() string { if t == nil || t.Title == nil { return "" } return *t.Title } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetUpdatedAt() Timestamp { if t == nil || t.UpdatedAt == nil { return Timestamp{} } return *t.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (t *TeamDiscussion) GetURL() string { if t == nil || t.URL == nil { return "" } return *t.URL } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (t *TeamEvent) GetAction() string { if t == nil || t.Action == nil { return "" } return *t.Action } // GetChanges returns the Changes field. func (t *TeamEvent) GetChanges() *TeamChange { if t == nil { return nil } return t.Changes } // GetInstallation returns the Installation field. func (t *TeamEvent) GetInstallation() *Installation { if t == nil { return nil } return t.Installation } // GetOrg returns the Org field. func (t *TeamEvent) GetOrg() *Organization { if t == nil { return nil } return t.Org } // GetRepo returns the Repo field. func (t *TeamEvent) GetRepo() *Repository { if t == nil { return nil } return t.Repo } // GetSender returns the Sender field. func (t *TeamEvent) GetSender() *User { if t == nil { return nil } return t.Sender } // GetTeam returns the Team field. func (t *TeamEvent) GetTeam() *Team { if t == nil { return nil } return t.Team } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (t *TeamLDAPMapping) GetDescription() string { if t == nil || t.Description == nil { return "" } return *t.Description } // GetID returns the ID field if it's non-nil, zero value otherwise. func (t *TeamLDAPMapping) GetID() int64 { if t == nil || t.ID == nil { return 0 } return *t.ID } // GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. func (t *TeamLDAPMapping) GetLDAPDN() string { if t == nil || t.LDAPDN == nil { return "" } return *t.LDAPDN } // GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. func (t *TeamLDAPMapping) GetMembersURL() string { if t == nil || t.MembersURL == nil { return "" } return *t.MembersURL } // GetName returns the Name field if it's non-nil, zero value otherwise. func (t *TeamLDAPMapping) GetName() string { if t == nil || t.Name == nil { return "" } return *t.Name } // GetPermission returns the Permission field if it's non-nil, zero value otherwise. func (t *TeamLDAPMapping) GetPermission() string { if t == nil || t.Permission == nil { return "" } return *t.Permission } // GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. func (t *TeamLDAPMapping) GetPrivacy() string { if t == nil || t.Privacy == nil { return "" } return *t.Privacy } // GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. func (t *TeamLDAPMapping) GetRepositoriesURL() string { if t == nil || t.RepositoriesURL == nil { return "" } return *t.RepositoriesURL } // GetSlug returns the Slug field if it's non-nil, zero value otherwise. func (t *TeamLDAPMapping) GetSlug() string { if t == nil || t.Slug == nil { return "" } return *t.Slug } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (t *TeamLDAPMapping) GetURL() string { if t == nil || t.URL == nil { return "" } return *t.URL } // GetPermission returns the Permission field if it's non-nil, zero value otherwise. func (t *TeamProjectOptions) GetPermission() string { if t == nil || t.Permission == nil { return "" } return *t.Permission } // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (t *TemplateRepoRequest) GetDescription() string { if t == nil || t.Description == nil { return "" } return *t.Description } // GetName returns the Name field if it's non-nil, zero value otherwise. func (t *TemplateRepoRequest) GetName() string { if t == nil || t.Name == nil { return "" } return *t.Name } // GetOwner returns the Owner field if it's non-nil, zero value otherwise. func (t *TemplateRepoRequest) GetOwner() string { if t == nil || t.Owner == nil { return "" } return *t.Owner } // GetPrivate returns the Private field if it's non-nil, zero value otherwise. func (t *TemplateRepoRequest) GetPrivate() bool { if t == nil || t.Private == nil { return false } return *t.Private } // GetFragment returns the Fragment field if it's non-nil, zero value otherwise. func (t *TextMatch) GetFragment() string { if t == nil || t.Fragment == nil { return "" } return *t.Fragment } // GetObjectType returns the ObjectType field if it's non-nil, zero value otherwise. func (t *TextMatch) GetObjectType() string { if t == nil || t.ObjectType == nil { return "" } return *t.ObjectType } // GetObjectURL returns the ObjectURL field if it's non-nil, zero value otherwise. func (t *TextMatch) GetObjectURL() string { if t == nil || t.ObjectURL == nil { return "" } return *t.ObjectURL } // GetProperty returns the Property field if it's non-nil, zero value otherwise. func (t *TextMatch) GetProperty() string { if t == nil || t.Property == nil { return "" } return *t.Property } // GetActor returns the Actor field. func (t *Timeline) GetActor() *User { if t == nil { return nil } return t.Actor } // GetAssignee returns the Assignee field. func (t *Timeline) GetAssignee() *User { if t == nil { return nil } return t.Assignee } // GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. func (t *Timeline) GetCommitID() string { if t == nil || t.CommitID == nil { return "" } return *t.CommitID } // GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. func (t *Timeline) GetCommitURL() string { if t == nil || t.CommitURL == nil { return "" } return *t.CommitURL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (t *Timeline) GetCreatedAt() time.Time { if t == nil || t.CreatedAt == nil { return time.Time{} } return *t.CreatedAt } // GetEvent returns the Event field if it's non-nil, zero value otherwise. func (t *Timeline) GetEvent() string { if t == nil || t.Event == nil { return "" } return *t.Event } // GetID returns the ID field if it's non-nil, zero value otherwise. func (t *Timeline) GetID() int64 { if t == nil || t.ID == nil { return 0 } return *t.ID } // GetLabel returns the Label field. func (t *Timeline) GetLabel() *Label { if t == nil { return nil } return t.Label } // GetMilestone returns the Milestone field. func (t *Timeline) GetMilestone() *Milestone { if t == nil { return nil } return t.Milestone } // GetProjectCard returns the ProjectCard field. func (t *Timeline) GetProjectCard() *ProjectCard { if t == nil { return nil } return t.ProjectCard } // GetRename returns the Rename field. func (t *Timeline) GetRename() *Rename { if t == nil { return nil } return t.Rename } // GetSource returns the Source field. func (t *Timeline) GetSource() *Source { if t == nil { return nil } return t.Source } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (t *Timeline) GetURL() string { if t == nil || t.URL == nil { return "" } return *t.URL } // GetCount returns the Count field if it's non-nil, zero value otherwise. func (t *TrafficClones) GetCount() int { if t == nil || t.Count == nil { return 0 } return *t.Count } // GetUniques returns the Uniques field if it's non-nil, zero value otherwise. func (t *TrafficClones) GetUniques() int { if t == nil || t.Uniques == nil { return 0 } return *t.Uniques } // GetCount returns the Count field if it's non-nil, zero value otherwise. func (t *TrafficData) GetCount() int { if t == nil || t.Count == nil { return 0 } return *t.Count } // GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. func (t *TrafficData) GetTimestamp() Timestamp { if t == nil || t.Timestamp == nil { return Timestamp{} } return *t.Timestamp } // GetUniques returns the Uniques field if it's non-nil, zero value otherwise. func (t *TrafficData) GetUniques() int { if t == nil || t.Uniques == nil { return 0 } return *t.Uniques } // GetCount returns the Count field if it's non-nil, zero value otherwise. func (t *TrafficPath) GetCount() int { if t == nil || t.Count == nil { return 0 } return *t.Count } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (t *TrafficPath) GetPath() string { if t == nil || t.Path == nil { return "" } return *t.Path } // GetTitle returns the Title field if it's non-nil, zero value otherwise. func (t *TrafficPath) GetTitle() string { if t == nil || t.Title == nil { return "" } return *t.Title } // GetUniques returns the Uniques field if it's non-nil, zero value otherwise. func (t *TrafficPath) GetUniques() int { if t == nil || t.Uniques == nil { return 0 } return *t.Uniques } // GetCount returns the Count field if it's non-nil, zero value otherwise. func (t *TrafficReferrer) GetCount() int { if t == nil || t.Count == nil { return 0 } return *t.Count } // GetReferrer returns the Referrer field if it's non-nil, zero value otherwise. func (t *TrafficReferrer) GetReferrer() string { if t == nil || t.Referrer == nil { return "" } return *t.Referrer } // GetUniques returns the Uniques field if it's non-nil, zero value otherwise. func (t *TrafficReferrer) GetUniques() int { if t == nil || t.Uniques == nil { return 0 } return *t.Uniques } // GetCount returns the Count field if it's non-nil, zero value otherwise. func (t *TrafficViews) GetCount() int { if t == nil || t.Count == nil { return 0 } return *t.Count } // GetUniques returns the Uniques field if it's non-nil, zero value otherwise. func (t *TrafficViews) GetUniques() int { if t == nil || t.Uniques == nil { return 0 } return *t.Uniques } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (t *Tree) GetSHA() string { if t == nil || t.SHA == nil { return "" } return *t.SHA } // GetTruncated returns the Truncated field if it's non-nil, zero value otherwise. func (t *Tree) GetTruncated() bool { if t == nil || t.Truncated == nil { return false } return *t.Truncated } // GetContent returns the Content field if it's non-nil, zero value otherwise. func (t *TreeEntry) GetContent() string { if t == nil || t.Content == nil { return "" } return *t.Content } // GetMode returns the Mode field if it's non-nil, zero value otherwise. func (t *TreeEntry) GetMode() string { if t == nil || t.Mode == nil { return "" } return *t.Mode } // GetPath returns the Path field if it's non-nil, zero value otherwise. func (t *TreeEntry) GetPath() string { if t == nil || t.Path == nil { return "" } return *t.Path } // GetSHA returns the SHA field if it's non-nil, zero value otherwise. func (t *TreeEntry) GetSHA() string { if t == nil || t.SHA == nil { return "" } return *t.SHA } // GetSize returns the Size field if it's non-nil, zero value otherwise. func (t *TreeEntry) GetSize() int { if t == nil || t.Size == nil { return 0 } return *t.Size } // GetType returns the Type field if it's non-nil, zero value otherwise. func (t *TreeEntry) GetType() string { if t == nil || t.Type == nil { return "" } return *t.Type } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (t *TreeEntry) GetURL() string { if t == nil || t.URL == nil { return "" } return *t.URL } // GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. func (u *UpdateCheckRunOptions) GetCompletedAt() Timestamp { if u == nil || u.CompletedAt == nil { return Timestamp{} } return *u.CompletedAt } // GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. func (u *UpdateCheckRunOptions) GetConclusion() string { if u == nil || u.Conclusion == nil { return "" } return *u.Conclusion } // GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. func (u *UpdateCheckRunOptions) GetDetailsURL() string { if u == nil || u.DetailsURL == nil { return "" } return *u.DetailsURL } // GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. func (u *UpdateCheckRunOptions) GetExternalID() string { if u == nil || u.ExternalID == nil { return "" } return *u.ExternalID } // GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. func (u *UpdateCheckRunOptions) GetHeadBranch() string { if u == nil || u.HeadBranch == nil { return "" } return *u.HeadBranch } // GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. func (u *UpdateCheckRunOptions) GetHeadSHA() string { if u == nil || u.HeadSHA == nil { return "" } return *u.HeadSHA } // GetOutput returns the Output field. func (u *UpdateCheckRunOptions) GetOutput() *CheckRunOutput { if u == nil { return nil } return u.Output } // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (u *UpdateCheckRunOptions) GetStatus() string { if u == nil || u.Status == nil { return "" } return *u.Status } // GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. func (u *User) GetAvatarURL() string { if u == nil || u.AvatarURL == nil { return "" } return *u.AvatarURL } // GetBio returns the Bio field if it's non-nil, zero value otherwise. func (u *User) GetBio() string { if u == nil || u.Bio == nil { return "" } return *u.Bio } // GetBlog returns the Blog field if it's non-nil, zero value otherwise. func (u *User) GetBlog() string { if u == nil || u.Blog == nil { return "" } return *u.Blog } // GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. func (u *User) GetCollaborators() int { if u == nil || u.Collaborators == nil { return 0 } return *u.Collaborators } // GetCompany returns the Company field if it's non-nil, zero value otherwise. func (u *User) GetCompany() string { if u == nil || u.Company == nil { return "" } return *u.Company } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (u *User) GetCreatedAt() Timestamp { if u == nil || u.CreatedAt == nil { return Timestamp{} } return *u.CreatedAt } // GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. func (u *User) GetDiskUsage() int { if u == nil || u.DiskUsage == nil { return 0 } return *u.DiskUsage } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (u *User) GetEmail() string { if u == nil || u.Email == nil { return "" } return *u.Email } // GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. func (u *User) GetEventsURL() string { if u == nil || u.EventsURL == nil { return "" } return *u.EventsURL } // GetFollowers returns the Followers field if it's non-nil, zero value otherwise. func (u *User) GetFollowers() int { if u == nil || u.Followers == nil { return 0 } return *u.Followers } // GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. func (u *User) GetFollowersURL() string { if u == nil || u.FollowersURL == nil { return "" } return *u.FollowersURL } // GetFollowing returns the Following field if it's non-nil, zero value otherwise. func (u *User) GetFollowing() int { if u == nil || u.Following == nil { return 0 } return *u.Following } // GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. func (u *User) GetFollowingURL() string { if u == nil || u.FollowingURL == nil { return "" } return *u.FollowingURL } // GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. func (u *User) GetGistsURL() string { if u == nil || u.GistsURL == nil { return "" } return *u.GistsURL } // GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. func (u *User) GetGravatarID() string { if u == nil || u.GravatarID == nil { return "" } return *u.GravatarID } // GetHireable returns the Hireable field if it's non-nil, zero value otherwise. func (u *User) GetHireable() bool { if u == nil || u.Hireable == nil { return false } return *u.Hireable } // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (u *User) GetHTMLURL() string { if u == nil || u.HTMLURL == nil { return "" } return *u.HTMLURL } // GetID returns the ID field if it's non-nil, zero value otherwise. func (u *User) GetID() int64 { if u == nil || u.ID == nil { return 0 } return *u.ID } // GetLdapDn returns the LdapDn field if it's non-nil, zero value otherwise. func (u *User) GetLdapDn() string { if u == nil || u.LdapDn == nil { return "" } return *u.LdapDn } // GetLocation returns the Location field if it's non-nil, zero value otherwise. func (u *User) GetLocation() string { if u == nil || u.Location == nil { return "" } return *u.Location } // GetLogin returns the Login field if it's non-nil, zero value otherwise. func (u *User) GetLogin() string { if u == nil || u.Login == nil { return "" } return *u.Login } // GetName returns the Name field if it's non-nil, zero value otherwise. func (u *User) GetName() string { if u == nil || u.Name == nil { return "" } return *u.Name } // GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. func (u *User) GetNodeID() string { if u == nil || u.NodeID == nil { return "" } return *u.NodeID } // GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. func (u *User) GetOrganizationsURL() string { if u == nil || u.OrganizationsURL == nil { return "" } return *u.OrganizationsURL } // GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. func (u *User) GetOwnedPrivateRepos() int { if u == nil || u.OwnedPrivateRepos == nil { return 0 } return *u.OwnedPrivateRepos } // GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. func (u *User) GetPermissions() map[string]bool { if u == nil || u.Permissions == nil { return map[string]bool{} } return *u.Permissions } // GetPlan returns the Plan field. func (u *User) GetPlan() *Plan { if u == nil { return nil } return u.Plan } // GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. func (u *User) GetPrivateGists() int { if u == nil || u.PrivateGists == nil { return 0 } return *u.PrivateGists } // GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. func (u *User) GetPublicGists() int { if u == nil || u.PublicGists == nil { return 0 } return *u.PublicGists } // GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. func (u *User) GetPublicRepos() int { if u == nil || u.PublicRepos == nil { return 0 } return *u.PublicRepos } // GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. func (u *User) GetReceivedEventsURL() string { if u == nil || u.ReceivedEventsURL == nil { return "" } return *u.ReceivedEventsURL } // GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. func (u *User) GetReposURL() string { if u == nil || u.ReposURL == nil { return "" } return *u.ReposURL } // GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. func (u *User) GetSiteAdmin() bool { if u == nil || u.SiteAdmin == nil { return false } return *u.SiteAdmin } // GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. func (u *User) GetStarredURL() string { if u == nil || u.StarredURL == nil { return "" } return *u.StarredURL } // GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. func (u *User) GetSubscriptionsURL() string { if u == nil || u.SubscriptionsURL == nil { return "" } return *u.SubscriptionsURL } // GetSuspendedAt returns the SuspendedAt field if it's non-nil, zero value otherwise. func (u *User) GetSuspendedAt() Timestamp { if u == nil || u.SuspendedAt == nil { return Timestamp{} } return *u.SuspendedAt } // GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. func (u *User) GetTotalPrivateRepos() int { if u == nil || u.TotalPrivateRepos == nil { return 0 } return *u.TotalPrivateRepos } // GetTwoFactorAuthentication returns the TwoFactorAuthentication field if it's non-nil, zero value otherwise. func (u *User) GetTwoFactorAuthentication() bool { if u == nil || u.TwoFactorAuthentication == nil { return false } return *u.TwoFactorAuthentication } // GetType returns the Type field if it's non-nil, zero value otherwise. func (u *User) GetType() string { if u == nil || u.Type == nil { return "" } return *u.Type } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (u *User) GetUpdatedAt() Timestamp { if u == nil || u.UpdatedAt == nil { return Timestamp{} } return *u.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (u *User) GetURL() string { if u == nil || u.URL == nil { return "" } return *u.URL } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (u *UserContext) GetMessage() string { if u == nil || u.Message == nil { return "" } return *u.Message } // GetOcticon returns the Octicon field if it's non-nil, zero value otherwise. func (u *UserContext) GetOcticon() string { if u == nil || u.Octicon == nil { return "" } return *u.Octicon } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (u *UserEmail) GetEmail() string { if u == nil || u.Email == nil { return "" } return *u.Email } // GetPrimary returns the Primary field if it's non-nil, zero value otherwise. func (u *UserEmail) GetPrimary() bool { if u == nil || u.Primary == nil { return false } return *u.Primary } // GetVerified returns the Verified field if it's non-nil, zero value otherwise. func (u *UserEmail) GetVerified() bool { if u == nil || u.Verified == nil { return false } return *u.Verified } // GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. func (u *UserEmail) GetVisibility() string { if u == nil || u.Visibility == nil { return "" } return *u.Visibility } // GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetAvatarURL() string { if u == nil || u.AvatarURL == nil { return "" } return *u.AvatarURL } // GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetEventsURL() string { if u == nil || u.EventsURL == nil { return "" } return *u.EventsURL } // GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetFollowersURL() string { if u == nil || u.FollowersURL == nil { return "" } return *u.FollowersURL } // GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetFollowingURL() string { if u == nil || u.FollowingURL == nil { return "" } return *u.FollowingURL } // GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetGistsURL() string { if u == nil || u.GistsURL == nil { return "" } return *u.GistsURL } // GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetGravatarID() string { if u == nil || u.GravatarID == nil { return "" } return *u.GravatarID } // GetID returns the ID field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetID() int64 { if u == nil || u.ID == nil { return 0 } return *u.ID } // GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetLDAPDN() string { if u == nil || u.LDAPDN == nil { return "" } return *u.LDAPDN } // GetLogin returns the Login field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetLogin() string { if u == nil || u.Login == nil { return "" } return *u.Login } // GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetOrganizationsURL() string { if u == nil || u.OrganizationsURL == nil { return "" } return *u.OrganizationsURL } // GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetReceivedEventsURL() string { if u == nil || u.ReceivedEventsURL == nil { return "" } return *u.ReceivedEventsURL } // GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetReposURL() string { if u == nil || u.ReposURL == nil { return "" } return *u.ReposURL } // GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetSiteAdmin() bool { if u == nil || u.SiteAdmin == nil { return false } return *u.SiteAdmin } // GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetStarredURL() string { if u == nil || u.StarredURL == nil { return "" } return *u.StarredURL } // GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetSubscriptionsURL() string { if u == nil || u.SubscriptionsURL == nil { return "" } return *u.SubscriptionsURL } // GetType returns the Type field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetType() string { if u == nil || u.Type == nil { return "" } return *u.Type } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (u *UserLDAPMapping) GetURL() string { if u == nil || u.URL == nil { return "" } return *u.URL } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (u *UserMigration) GetCreatedAt() string { if u == nil || u.CreatedAt == nil { return "" } return *u.CreatedAt } // GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. func (u *UserMigration) GetExcludeAttachments() bool { if u == nil || u.ExcludeAttachments == nil { return false } return *u.ExcludeAttachments } // GetGUID returns the GUID field if it's non-nil, zero value otherwise. func (u *UserMigration) GetGUID() string { if u == nil || u.GUID == nil { return "" } return *u.GUID } // GetID returns the ID field if it's non-nil, zero value otherwise. func (u *UserMigration) GetID() int64 { if u == nil || u.ID == nil { return 0 } return *u.ID } // GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. func (u *UserMigration) GetLockRepositories() bool { if u == nil || u.LockRepositories == nil { return false } return *u.LockRepositories } // GetState returns the State field if it's non-nil, zero value otherwise. func (u *UserMigration) GetState() string { if u == nil || u.State == nil { return "" } return *u.State } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (u *UserMigration) GetUpdatedAt() string { if u == nil || u.UpdatedAt == nil { return "" } return *u.UpdatedAt } // GetURL returns the URL field if it's non-nil, zero value otherwise. func (u *UserMigration) GetURL() string { if u == nil || u.URL == nil { return "" } return *u.URL } // GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. func (u *UsersSearchResult) GetIncompleteResults() bool { if u == nil || u.IncompleteResults == nil { return false } return *u.IncompleteResults } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (u *UsersSearchResult) GetTotal() int { if u == nil || u.Total == nil { return 0 } return *u.Total } // GetAdminUsers returns the AdminUsers field if it's non-nil, zero value otherwise. func (u *UserStats) GetAdminUsers() int { if u == nil || u.AdminUsers == nil { return 0 } return *u.AdminUsers } // GetSuspendedUsers returns the SuspendedUsers field if it's non-nil, zero value otherwise. func (u *UserStats) GetSuspendedUsers() int { if u == nil || u.SuspendedUsers == nil { return 0 } return *u.SuspendedUsers } // GetTotalUsers returns the TotalUsers field if it's non-nil, zero value otherwise. func (u *UserStats) GetTotalUsers() int { if u == nil || u.TotalUsers == nil { return 0 } return *u.TotalUsers } // GetReason returns the Reason field if it's non-nil, zero value otherwise. func (u *UserSuspendOptions) GetReason() string { if u == nil || u.Reason == nil { return "" } return *u.Reason } // GetAction returns the Action field if it's non-nil, zero value otherwise. func (w *WatchEvent) GetAction() string { if w == nil || w.Action == nil { return "" } return *w.Action } // GetInstallation returns the Installation field. func (w *WatchEvent) GetInstallation() *Installation { if w == nil { return nil } return w.Installation } // GetRepo returns the Repo field. func (w *WatchEvent) GetRepo() *Repository { if w == nil { return nil } return w.Repo } // GetSender returns the Sender field. func (w *WatchEvent) GetSender() *User { if w == nil { return nil } return w.Sender } // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (w *WebHookAuthor) GetEmail() string { if w == nil || w.Email == nil { return "" } return *w.Email } // GetName returns the Name field if it's non-nil, zero value otherwise. func (w *WebHookAuthor) GetName() string { if w == nil || w.Name == nil { return "" } return *w.Name } // GetUsername returns the Username field if it's non-nil, zero value otherwise. func (w *WebHookAuthor) GetUsername() string { if w == nil || w.Username == nil { return "" } return *w.Username } // GetAuthor returns the Author field. func (w *WebHookCommit) GetAuthor() *WebHookAuthor { if w == nil { return nil } return w.Author } // GetCommitter returns the Committer field. func (w *WebHookCommit) GetCommitter() *WebHookAuthor { if w == nil { return nil } return w.Committer } // GetDistinct returns the Distinct field if it's non-nil, zero value otherwise. func (w *WebHookCommit) GetDistinct() bool { if w == nil || w.Distinct == nil { return false } return *w.Distinct } // GetID returns the ID field if it's non-nil, zero value otherwise. func (w *WebHookCommit) GetID() string { if w == nil || w.ID == nil { return "" } return *w.ID } // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (w *WebHookCommit) GetMessage() string { if w == nil || w.Message == nil { return "" } return *w.Message } // GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. func (w *WebHookCommit) GetTimestamp() time.Time { if w == nil || w.Timestamp == nil { return time.Time{} } return *w.Timestamp } // GetAfter returns the After field if it's non-nil, zero value otherwise. func (w *WebHookPayload) GetAfter() string { if w == nil || w.After == nil { return "" } return *w.After } // GetBefore returns the Before field if it's non-nil, zero value otherwise. func (w *WebHookPayload) GetBefore() string { if w == nil || w.Before == nil { return "" } return *w.Before } // GetCompare returns the Compare field if it's non-nil, zero value otherwise. func (w *WebHookPayload) GetCompare() string { if w == nil || w.Compare == nil { return "" } return *w.Compare } // GetCreated returns the Created field if it's non-nil, zero value otherwise. func (w *WebHookPayload) GetCreated() bool { if w == nil || w.Created == nil { return false } return *w.Created } // GetDeleted returns the Deleted field if it's non-nil, zero value otherwise. func (w *WebHookPayload) GetDeleted() bool { if w == nil || w.Deleted == nil { return false } return *w.Deleted } // GetForced returns the Forced field if it's non-nil, zero value otherwise. func (w *WebHookPayload) GetForced() bool { if w == nil || w.Forced == nil { return false } return *w.Forced } // GetHeadCommit returns the HeadCommit field. func (w *WebHookPayload) GetHeadCommit() *WebHookCommit { if w == nil { return nil } return w.HeadCommit } // GetPusher returns the Pusher field. func (w *WebHookPayload) GetPusher() *User { if w == nil { return nil } return w.Pusher } // GetRef returns the Ref field if it's non-nil, zero value otherwise. func (w *WebHookPayload) GetRef() string { if w == nil || w.Ref == nil { return "" } return *w.Ref } // GetRepo returns the Repo field. func (w *WebHookPayload) GetRepo() *Repository { if w == nil { return nil } return w.Repo } // GetSender returns the Sender field. func (w *WebHookPayload) GetSender() *User { if w == nil { return nil } return w.Sender } // GetTotal returns the Total field if it's non-nil, zero value otherwise. func (w *WeeklyCommitActivity) GetTotal() int { if w == nil || w.Total == nil { return 0 } return *w.Total } // GetWeek returns the Week field if it's non-nil, zero value otherwise. func (w *WeeklyCommitActivity) GetWeek() Timestamp { if w == nil || w.Week == nil { return Timestamp{} } return *w.Week } // GetAdditions returns the Additions field if it's non-nil, zero value otherwise. func (w *WeeklyStats) GetAdditions() int { if w == nil || w.Additions == nil { return 0 } return *w.Additions } // GetCommits returns the Commits field if it's non-nil, zero value otherwise. func (w *WeeklyStats) GetCommits() int { if w == nil || w.Commits == nil { return 0 } return *w.Commits } // GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. func (w *WeeklyStats) GetDeletions() int { if w == nil || w.Deletions == nil { return 0 } return *w.Deletions } // GetWeek returns the Week field if it's non-nil, zero value otherwise. func (w *WeeklyStats) GetWeek() Timestamp { if w == nil || w.Week == nil { return Timestamp{} } return *w.Week } go-github-28.1.1/github/github-stringify_test.go000066400000000000000000001611331353501270500216440ustar00rootroot00000000000000// Copyright 2019 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by gen-stringify-tests; DO NOT EDIT. package github import ( "testing" ) func Float64(v float64) *float64 { return &v } func TestAdminStats_String(t *testing.T) { v := AdminStats{ Issues: &IssueStats{}, Hooks: &HookStats{}, Milestones: &MilestoneStats{}, Orgs: &OrgStats{}, Comments: &CommentStats{}, Pages: &PageStats{}, Users: &UserStats{}, Gists: &GistStats{}, Pulls: &PullStats{}, Repos: &RepoStats{}, } want := `github.AdminStats{Issues:github.IssueStats{}, Hooks:github.HookStats{}, Milestones:github.MilestoneStats{}, Orgs:github.OrgStats{}, Comments:github.CommentStats{}, Pages:github.PageStats{}, Users:github.UserStats{}, Gists:github.GistStats{}, Pulls:github.PullStats{}, Repos:github.RepoStats{}}` if got := v.String(); got != want { t.Errorf("AdminStats.String = %v, want %v", got, want) } } func TestAuthorization_String(t *testing.T) { v := Authorization{ ID: Int64(0), URL: String(""), Token: String(""), TokenLastEight: String(""), HashedToken: String(""), App: &AuthorizationApp{}, Note: String(""), NoteURL: String(""), UpdatedAt: &Timestamp{}, CreatedAt: &Timestamp{}, Fingerprint: String(""), User: &User{}, } want := `github.Authorization{ID:0, URL:"", Token:"", TokenLastEight:"", HashedToken:"", App:github.AuthorizationApp{}, Note:"", NoteURL:"", UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, Fingerprint:"", User:github.User{}}` if got := v.String(); got != want { t.Errorf("Authorization.String = %v, want %v", got, want) } } func TestAuthorizationApp_String(t *testing.T) { v := AuthorizationApp{ URL: String(""), Name: String(""), ClientID: String(""), } want := `github.AuthorizationApp{URL:"", Name:"", ClientID:""}` if got := v.String(); got != want { t.Errorf("AuthorizationApp.String = %v, want %v", got, want) } } func TestAuthorizationRequest_String(t *testing.T) { v := AuthorizationRequest{ Note: String(""), NoteURL: String(""), ClientID: String(""), ClientSecret: String(""), Fingerprint: String(""), } want := `github.AuthorizationRequest{Note:"", NoteURL:"", ClientID:"", ClientSecret:"", Fingerprint:""}` if got := v.String(); got != want { t.Errorf("AuthorizationRequest.String = %v, want %v", got, want) } } func TestAuthorizationUpdateRequest_String(t *testing.T) { v := AuthorizationUpdateRequest{ Note: String(""), NoteURL: String(""), Fingerprint: String(""), } want := `github.AuthorizationUpdateRequest{Note:"", NoteURL:"", Fingerprint:""}` if got := v.String(); got != want { t.Errorf("AuthorizationUpdateRequest.String = %v, want %v", got, want) } } func TestCheckRun_String(t *testing.T) { v := CheckRun{ ID: Int64(0), NodeID: String(""), HeadSHA: String(""), ExternalID: String(""), URL: String(""), HTMLURL: String(""), DetailsURL: String(""), Status: String(""), Conclusion: String(""), StartedAt: &Timestamp{}, CompletedAt: &Timestamp{}, Output: &CheckRunOutput{}, Name: String(""), CheckSuite: &CheckSuite{}, App: &App{}, } want := `github.CheckRun{ID:0, NodeID:"", HeadSHA:"", ExternalID:"", URL:"", HTMLURL:"", DetailsURL:"", Status:"", Conclusion:"", StartedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, CompletedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, Output:github.CheckRunOutput{}, Name:"", CheckSuite:github.CheckSuite{}, App:github.App{}}` if got := v.String(); got != want { t.Errorf("CheckRun.String = %v, want %v", got, want) } } func TestCheckSuite_String(t *testing.T) { v := CheckSuite{ ID: Int64(0), NodeID: String(""), HeadBranch: String(""), HeadSHA: String(""), URL: String(""), BeforeSHA: String(""), AfterSHA: String(""), Status: String(""), Conclusion: String(""), App: &App{}, Repository: &Repository{}, HeadCommit: &Commit{}, } want := `github.CheckSuite{ID:0, NodeID:"", HeadBranch:"", HeadSHA:"", URL:"", BeforeSHA:"", AfterSHA:"", Status:"", Conclusion:"", App:github.App{}, Repository:github.Repository{}, HeadCommit:github.Commit{}}` if got := v.String(); got != want { t.Errorf("CheckSuite.String = %v, want %v", got, want) } } func TestCodeResult_String(t *testing.T) { v := CodeResult{ Name: String(""), Path: String(""), SHA: String(""), HTMLURL: String(""), Repository: &Repository{}, } want := `github.CodeResult{Name:"", Path:"", SHA:"", HTMLURL:"", Repository:github.Repository{}}` if got := v.String(); got != want { t.Errorf("CodeResult.String = %v, want %v", got, want) } } func TestCombinedStatus_String(t *testing.T) { v := CombinedStatus{ State: String(""), Name: String(""), SHA: String(""), TotalCount: Int(0), CommitURL: String(""), RepositoryURL: String(""), } want := `github.CombinedStatus{State:"", Name:"", SHA:"", TotalCount:0, CommitURL:"", RepositoryURL:""}` if got := v.String(); got != want { t.Errorf("CombinedStatus.String = %v, want %v", got, want) } } func TestCommentStats_String(t *testing.T) { v := CommentStats{ TotalCommitComments: Int(0), TotalGistComments: Int(0), TotalIssueComments: Int(0), TotalPullRequestComments: Int(0), } want := `github.CommentStats{TotalCommitComments:0, TotalGistComments:0, TotalIssueComments:0, TotalPullRequestComments:0}` if got := v.String(); got != want { t.Errorf("CommentStats.String = %v, want %v", got, want) } } func TestCommit_String(t *testing.T) { v := Commit{ SHA: String(""), Author: &CommitAuthor{}, Committer: &CommitAuthor{}, Message: String(""), Tree: &Tree{}, Stats: &CommitStats{}, HTMLURL: String(""), URL: String(""), Verification: &SignatureVerification{}, NodeID: String(""), CommentCount: Int(0), } want := `github.Commit{SHA:"", Author:github.CommitAuthor{}, Committer:github.CommitAuthor{}, Message:"", Tree:github.Tree{}, Stats:github.CommitStats{}, HTMLURL:"", URL:"", Verification:github.SignatureVerification{}, NodeID:"", CommentCount:0}` if got := v.String(); got != want { t.Errorf("Commit.String = %v, want %v", got, want) } } func TestCommitAuthor_String(t *testing.T) { v := CommitAuthor{ Name: String(""), Email: String(""), Login: String(""), } want := `github.CommitAuthor{Name:"", Email:"", Login:""}` if got := v.String(); got != want { t.Errorf("CommitAuthor.String = %v, want %v", got, want) } } func TestCommitFile_String(t *testing.T) { v := CommitFile{ SHA: String(""), Filename: String(""), Additions: Int(0), Deletions: Int(0), Changes: Int(0), Status: String(""), Patch: String(""), BlobURL: String(""), RawURL: String(""), ContentsURL: String(""), PreviousFilename: String(""), } want := `github.CommitFile{SHA:"", Filename:"", Additions:0, Deletions:0, Changes:0, Status:"", Patch:"", BlobURL:"", RawURL:"", ContentsURL:"", PreviousFilename:""}` if got := v.String(); got != want { t.Errorf("CommitFile.String = %v, want %v", got, want) } } func TestCommitStats_String(t *testing.T) { v := CommitStats{ Additions: Int(0), Deletions: Int(0), Total: Int(0), } want := `github.CommitStats{Additions:0, Deletions:0, Total:0}` if got := v.String(); got != want { t.Errorf("CommitStats.String = %v, want %v", got, want) } } func TestCommitsComparison_String(t *testing.T) { v := CommitsComparison{ BaseCommit: &RepositoryCommit{}, MergeBaseCommit: &RepositoryCommit{}, Status: String(""), AheadBy: Int(0), BehindBy: Int(0), TotalCommits: Int(0), HTMLURL: String(""), PermalinkURL: String(""), DiffURL: String(""), PatchURL: String(""), URL: String(""), } want := `github.CommitsComparison{BaseCommit:github.RepositoryCommit{}, MergeBaseCommit:github.RepositoryCommit{}, Status:"", AheadBy:0, BehindBy:0, TotalCommits:0, HTMLURL:"", PermalinkURL:"", DiffURL:"", PatchURL:"", URL:""}` if got := v.String(); got != want { t.Errorf("CommitsComparison.String = %v, want %v", got, want) } } func TestContributorStats_String(t *testing.T) { v := ContributorStats{ Author: &Contributor{}, Total: Int(0), } want := `github.ContributorStats{Author:github.Contributor{}, Total:0}` if got := v.String(); got != want { t.Errorf("ContributorStats.String = %v, want %v", got, want) } } func TestDiscussionComment_String(t *testing.T) { v := DiscussionComment{ Author: &User{}, Body: String(""), BodyHTML: String(""), BodyVersion: String(""), CreatedAt: &Timestamp{}, LastEditedAt: &Timestamp{}, DiscussionURL: String(""), HTMLURL: String(""), NodeID: String(""), Number: Int(0), UpdatedAt: &Timestamp{}, URL: String(""), Reactions: &Reactions{}, } want := `github.DiscussionComment{Author:github.User{}, Body:"", BodyHTML:"", BodyVersion:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, LastEditedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, DiscussionURL:"", HTMLURL:"", NodeID:"", Number:0, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, URL:"", Reactions:github.Reactions{}}` if got := v.String(); got != want { t.Errorf("DiscussionComment.String = %v, want %v", got, want) } } func TestDraftReviewComment_String(t *testing.T) { v := DraftReviewComment{ Path: String(""), Position: Int(0), Body: String(""), } want := `github.DraftReviewComment{Path:"", Position:0, Body:""}` if got := v.String(); got != want { t.Errorf("DraftReviewComment.String = %v, want %v", got, want) } } func TestEvent_String(t *testing.T) { v := Event{ Type: String(""), Public: Bool(false), Repo: &Repository{}, Actor: &User{}, Org: &Organization{}, ID: String(""), } want := `github.Event{Type:"", Public:false, Repo:github.Repository{}, Actor:github.User{}, Org:github.Organization{}, ID:""}` if got := v.String(); got != want { t.Errorf("Event.String = %v, want %v", got, want) } } func TestGPGKey_String(t *testing.T) { v := GPGKey{ ID: Int64(0), PrimaryKeyID: Int64(0), KeyID: String(""), PublicKey: String(""), CanSign: Bool(false), CanEncryptComms: Bool(false), CanEncryptStorage: Bool(false), CanCertify: Bool(false), } want := `github.GPGKey{ID:0, PrimaryKeyID:0, KeyID:"", PublicKey:"", CanSign:false, CanEncryptComms:false, CanEncryptStorage:false, CanCertify:false}` if got := v.String(); got != want { t.Errorf("GPGKey.String = %v, want %v", got, want) } } func TestGist_String(t *testing.T) { v := Gist{ ID: String(""), Description: String(""), Public: Bool(false), Owner: &User{}, Files: nil, Comments: Int(0), HTMLURL: String(""), GitPullURL: String(""), GitPushURL: String(""), NodeID: String(""), } want := `github.Gist{ID:"", Description:"", Public:false, Owner:github.User{}, Files:map[], Comments:0, HTMLURL:"", GitPullURL:"", GitPushURL:"", NodeID:""}` if got := v.String(); got != want { t.Errorf("Gist.String = %v, want %v", got, want) } } func TestGistComment_String(t *testing.T) { v := GistComment{ ID: Int64(0), URL: String(""), Body: String(""), User: &User{}, } want := `github.GistComment{ID:0, URL:"", Body:"", User:github.User{}}` if got := v.String(); got != want { t.Errorf("GistComment.String = %v, want %v", got, want) } } func TestGistCommit_String(t *testing.T) { v := GistCommit{ URL: String(""), Version: String(""), User: &User{}, ChangeStatus: &CommitStats{}, CommittedAt: &Timestamp{}, NodeID: String(""), } want := `github.GistCommit{URL:"", Version:"", User:github.User{}, ChangeStatus:github.CommitStats{}, CommittedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, NodeID:""}` if got := v.String(); got != want { t.Errorf("GistCommit.String = %v, want %v", got, want) } } func TestGistFile_String(t *testing.T) { v := GistFile{ Size: Int(0), Filename: String(""), Language: String(""), Type: String(""), RawURL: String(""), Content: String(""), } want := `github.GistFile{Size:0, Filename:"", Language:"", Type:"", RawURL:"", Content:""}` if got := v.String(); got != want { t.Errorf("GistFile.String = %v, want %v", got, want) } } func TestGistFork_String(t *testing.T) { v := GistFork{ URL: String(""), User: &User{}, ID: String(""), CreatedAt: &Timestamp{}, UpdatedAt: &Timestamp{}, NodeID: String(""), } want := `github.GistFork{URL:"", User:github.User{}, ID:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, NodeID:""}` if got := v.String(); got != want { t.Errorf("GistFork.String = %v, want %v", got, want) } } func TestGistStats_String(t *testing.T) { v := GistStats{ TotalGists: Int(0), PrivateGists: Int(0), PublicGists: Int(0), } want := `github.GistStats{TotalGists:0, PrivateGists:0, PublicGists:0}` if got := v.String(); got != want { t.Errorf("GistStats.String = %v, want %v", got, want) } } func TestGitObject_String(t *testing.T) { v := GitObject{ Type: String(""), SHA: String(""), URL: String(""), } want := `github.GitObject{Type:"", SHA:"", URL:""}` if got := v.String(); got != want { t.Errorf("GitObject.String = %v, want %v", got, want) } } func TestGitignore_String(t *testing.T) { v := Gitignore{ Name: String(""), Source: String(""), } want := `github.Gitignore{Name:"", Source:""}` if got := v.String(); got != want { t.Errorf("Gitignore.String = %v, want %v", got, want) } } func TestGrant_String(t *testing.T) { v := Grant{ ID: Int64(0), URL: String(""), App: &AuthorizationApp{}, CreatedAt: &Timestamp{}, UpdatedAt: &Timestamp{}, } want := `github.Grant{ID:0, URL:"", App:github.AuthorizationApp{}, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}` if got := v.String(); got != want { t.Errorf("Grant.String = %v, want %v", got, want) } } func TestHook_String(t *testing.T) { v := Hook{ URL: String(""), ID: Int64(0), Config: nil, Active: Bool(false), } want := `github.Hook{URL:"", ID:0, Config:map[], Active:false}` if got := v.String(); got != want { t.Errorf("Hook.String = %v, want %v", got, want) } } func TestHookStats_String(t *testing.T) { v := HookStats{ TotalHooks: Int(0), ActiveHooks: Int(0), InactiveHooks: Int(0), } want := `github.HookStats{TotalHooks:0, ActiveHooks:0, InactiveHooks:0}` if got := v.String(); got != want { t.Errorf("HookStats.String = %v, want %v", got, want) } } func TestImport_String(t *testing.T) { v := Import{ VCSURL: String(""), VCS: String(""), VCSUsername: String(""), VCSPassword: String(""), TFVCProject: String(""), UseLFS: String(""), HasLargeFiles: Bool(false), LargeFilesSize: Int(0), LargeFilesCount: Int(0), Status: String(""), CommitCount: Int(0), StatusText: String(""), AuthorsCount: Int(0), Percent: Int(0), PushPercent: Int(0), URL: String(""), HTMLURL: String(""), AuthorsURL: String(""), RepositoryURL: String(""), Message: String(""), FailedStep: String(""), HumanName: String(""), } want := `github.Import{VCSURL:"", VCS:"", VCSUsername:"", VCSPassword:"", TFVCProject:"", UseLFS:"", HasLargeFiles:false, LargeFilesSize:0, LargeFilesCount:0, Status:"", CommitCount:0, StatusText:"", AuthorsCount:0, Percent:0, PushPercent:0, URL:"", HTMLURL:"", AuthorsURL:"", RepositoryURL:"", Message:"", FailedStep:"", HumanName:""}` if got := v.String(); got != want { t.Errorf("Import.String = %v, want %v", got, want) } } func TestInstallation_String(t *testing.T) { v := Installation{ ID: Int64(0), AppID: Int64(0), TargetID: Int64(0), Account: &User{}, AccessTokensURL: String(""), RepositoriesURL: String(""), HTMLURL: String(""), TargetType: String(""), SingleFileName: String(""), RepositorySelection: String(""), Permissions: &InstallationPermissions{}, CreatedAt: &Timestamp{}, UpdatedAt: &Timestamp{}, } want := `github.Installation{ID:0, AppID:0, TargetID:0, Account:github.User{}, AccessTokensURL:"", RepositoriesURL:"", HTMLURL:"", TargetType:"", SingleFileName:"", RepositorySelection:"", Permissions:github.InstallationPermissions{}, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}` if got := v.String(); got != want { t.Errorf("Installation.String = %v, want %v", got, want) } } func TestInvitation_String(t *testing.T) { v := Invitation{ ID: Int64(0), NodeID: String(""), Login: String(""), Email: String(""), Role: String(""), Inviter: &User{}, TeamCount: Int(0), InvitationTeamURL: String(""), } want := `github.Invitation{ID:0, NodeID:"", Login:"", Email:"", Role:"", Inviter:github.User{}, TeamCount:0, InvitationTeamURL:""}` if got := v.String(); got != want { t.Errorf("Invitation.String = %v, want %v", got, want) } } func TestIssue_String(t *testing.T) { v := Issue{ ID: Int64(0), Number: Int(0), State: String(""), Locked: Bool(false), Title: String(""), Body: String(""), User: &User{}, Assignee: &User{}, Comments: Int(0), ClosedBy: &User{}, URL: String(""), HTMLURL: String(""), CommentsURL: String(""), EventsURL: String(""), LabelsURL: String(""), RepositoryURL: String(""), Milestone: &Milestone{}, PullRequestLinks: &PullRequestLinks{}, Repository: &Repository{}, Reactions: &Reactions{}, NodeID: String(""), ActiveLockReason: String(""), } want := `github.Issue{ID:0, Number:0, State:"", Locked:false, Title:"", Body:"", User:github.User{}, Assignee:github.User{}, Comments:0, ClosedBy:github.User{}, URL:"", HTMLURL:"", CommentsURL:"", EventsURL:"", LabelsURL:"", RepositoryURL:"", Milestone:github.Milestone{}, PullRequestLinks:github.PullRequestLinks{}, Repository:github.Repository{}, Reactions:github.Reactions{}, NodeID:"", ActiveLockReason:""}` if got := v.String(); got != want { t.Errorf("Issue.String = %v, want %v", got, want) } } func TestIssueComment_String(t *testing.T) { v := IssueComment{ ID: Int64(0), NodeID: String(""), Body: String(""), User: &User{}, Reactions: &Reactions{}, AuthorAssociation: String(""), URL: String(""), HTMLURL: String(""), IssueURL: String(""), } want := `github.IssueComment{ID:0, NodeID:"", Body:"", User:github.User{}, Reactions:github.Reactions{}, AuthorAssociation:"", URL:"", HTMLURL:"", IssueURL:""}` if got := v.String(); got != want { t.Errorf("IssueComment.String = %v, want %v", got, want) } } func TestIssueStats_String(t *testing.T) { v := IssueStats{ TotalIssues: Int(0), OpenIssues: Int(0), ClosedIssues: Int(0), } want := `github.IssueStats{TotalIssues:0, OpenIssues:0, ClosedIssues:0}` if got := v.String(); got != want { t.Errorf("IssueStats.String = %v, want %v", got, want) } } func TestKey_String(t *testing.T) { v := Key{ ID: Int64(0), Key: String(""), URL: String(""), Title: String(""), ReadOnly: Bool(false), CreatedAt: &Timestamp{}, } want := `github.Key{ID:0, Key:"", URL:"", Title:"", ReadOnly:false, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}` if got := v.String(); got != want { t.Errorf("Key.String = %v, want %v", got, want) } } func TestLabel_String(t *testing.T) { v := Label{ ID: Int64(0), URL: String(""), Name: String(""), Color: String(""), Description: String(""), Default: Bool(false), NodeID: String(""), } want := `github.Label{ID:0, URL:"", Name:"", Color:"", Description:"", Default:false, NodeID:""}` if got := v.String(); got != want { t.Errorf("Label.String = %v, want %v", got, want) } } func TestLabelResult_String(t *testing.T) { v := LabelResult{ ID: Int64(0), URL: String(""), Name: String(""), Color: String(""), Default: Bool(false), Description: String(""), Score: Float64(0.0), } want := `github.LabelResult{ID:0, URL:"", Name:"", Color:"", Default:false, Description:"", Score:0}` if got := v.String(); got != want { t.Errorf("LabelResult.String = %v, want %v", got, want) } } func TestLargeFile_String(t *testing.T) { v := LargeFile{ RefName: String(""), Path: String(""), OID: String(""), Size: Int(0), } want := `github.LargeFile{RefName:"", Path:"", OID:"", Size:0}` if got := v.String(); got != want { t.Errorf("LargeFile.String = %v, want %v", got, want) } } func TestLicense_String(t *testing.T) { v := License{ Key: String(""), Name: String(""), URL: String(""), SPDXID: String(""), HTMLURL: String(""), Featured: Bool(false), Description: String(""), Implementation: String(""), Body: String(""), } want := `github.License{Key:"", Name:"", URL:"", SPDXID:"", HTMLURL:"", Featured:false, Description:"", Implementation:"", Body:""}` if got := v.String(); got != want { t.Errorf("License.String = %v, want %v", got, want) } } func TestMembership_String(t *testing.T) { v := Membership{ URL: String(""), State: String(""), Role: String(""), OrganizationURL: String(""), Organization: &Organization{}, User: &User{}, } want := `github.Membership{URL:"", State:"", Role:"", OrganizationURL:"", Organization:github.Organization{}, User:github.User{}}` if got := v.String(); got != want { t.Errorf("Membership.String = %v, want %v", got, want) } } func TestMigration_String(t *testing.T) { v := Migration{ ID: Int64(0), GUID: String(""), State: String(""), LockRepositories: Bool(false), ExcludeAttachments: Bool(false), URL: String(""), CreatedAt: String(""), UpdatedAt: String(""), } want := `github.Migration{ID:0, GUID:"", State:"", LockRepositories:false, ExcludeAttachments:false, URL:"", CreatedAt:"", UpdatedAt:""}` if got := v.String(); got != want { t.Errorf("Migration.String = %v, want %v", got, want) } } func TestMilestone_String(t *testing.T) { v := Milestone{ URL: String(""), HTMLURL: String(""), LabelsURL: String(""), ID: Int64(0), Number: Int(0), State: String(""), Title: String(""), Description: String(""), Creator: &User{}, OpenIssues: Int(0), ClosedIssues: Int(0), NodeID: String(""), } want := `github.Milestone{URL:"", HTMLURL:"", LabelsURL:"", ID:0, Number:0, State:"", Title:"", Description:"", Creator:github.User{}, OpenIssues:0, ClosedIssues:0, NodeID:""}` if got := v.String(); got != want { t.Errorf("Milestone.String = %v, want %v", got, want) } } func TestMilestoneStats_String(t *testing.T) { v := MilestoneStats{ TotalMilestones: Int(0), OpenMilestones: Int(0), ClosedMilestones: Int(0), } want := `github.MilestoneStats{TotalMilestones:0, OpenMilestones:0, ClosedMilestones:0}` if got := v.String(); got != want { t.Errorf("MilestoneStats.String = %v, want %v", got, want) } } func TestNewTeam_String(t *testing.T) { v := NewTeam{ Name: "", Description: String(""), ParentTeamID: Int64(0), Permission: String(""), Privacy: String(""), LDAPDN: String(""), } want := `github.NewTeam{Name:"", Description:"", ParentTeamID:0, Permission:"", Privacy:"", LDAPDN:""}` if got := v.String(); got != want { t.Errorf("NewTeam.String = %v, want %v", got, want) } } func TestOrgStats_String(t *testing.T) { v := OrgStats{ TotalOrgs: Int(0), DisabledOrgs: Int(0), TotalTeams: Int(0), TotalTeamMembers: Int(0), } want := `github.OrgStats{TotalOrgs:0, DisabledOrgs:0, TotalTeams:0, TotalTeamMembers:0}` if got := v.String(); got != want { t.Errorf("OrgStats.String = %v, want %v", got, want) } } func TestOrganization_String(t *testing.T) { v := Organization{ Login: String(""), ID: Int64(0), NodeID: String(""), AvatarURL: String(""), HTMLURL: String(""), Name: String(""), Company: String(""), Blog: String(""), Location: String(""), Email: String(""), Description: String(""), PublicRepos: Int(0), PublicGists: Int(0), Followers: Int(0), Following: Int(0), TotalPrivateRepos: Int(0), OwnedPrivateRepos: Int(0), PrivateGists: Int(0), DiskUsage: Int(0), Collaborators: Int(0), BillingEmail: String(""), Type: String(""), Plan: &Plan{}, TwoFactorRequirementEnabled: Bool(false), DefaultRepoPermission: String(""), DefaultRepoSettings: String(""), MembersCanCreateRepos: Bool(false), MembersAllowedRepositoryCreationType: String(""), URL: String(""), EventsURL: String(""), HooksURL: String(""), IssuesURL: String(""), MembersURL: String(""), PublicMembersURL: String(""), ReposURL: String(""), } want := `github.Organization{Login:"", ID:0, NodeID:"", AvatarURL:"", HTMLURL:"", Name:"", Company:"", Blog:"", Location:"", Email:"", Description:"", PublicRepos:0, PublicGists:0, Followers:0, Following:0, TotalPrivateRepos:0, OwnedPrivateRepos:0, PrivateGists:0, DiskUsage:0, Collaborators:0, BillingEmail:"", Type:"", Plan:github.Plan{}, TwoFactorRequirementEnabled:false, DefaultRepoPermission:"", DefaultRepoSettings:"", MembersCanCreateRepos:false, MembersAllowedRepositoryCreationType:"", URL:"", EventsURL:"", HooksURL:"", IssuesURL:"", MembersURL:"", PublicMembersURL:"", ReposURL:""}` if got := v.String(); got != want { t.Errorf("Organization.String = %v, want %v", got, want) } } func TestPageStats_String(t *testing.T) { v := PageStats{ TotalPages: Int(0), } want := `github.PageStats{TotalPages:0}` if got := v.String(); got != want { t.Errorf("PageStats.String = %v, want %v", got, want) } } func TestPlan_String(t *testing.T) { v := Plan{ Name: String(""), Space: Int(0), Collaborators: Int(0), PrivateRepos: Int(0), } want := `github.Plan{Name:"", Space:0, Collaborators:0, PrivateRepos:0}` if got := v.String(); got != want { t.Errorf("Plan.String = %v, want %v", got, want) } } func TestPreReceiveHook_String(t *testing.T) { v := PreReceiveHook{ ID: Int64(0), Name: String(""), Enforcement: String(""), ConfigURL: String(""), } want := `github.PreReceiveHook{ID:0, Name:"", Enforcement:"", ConfigURL:""}` if got := v.String(); got != want { t.Errorf("PreReceiveHook.String = %v, want %v", got, want) } } func TestProject_String(t *testing.T) { v := Project{ ID: Int64(0), URL: String(""), HTMLURL: String(""), ColumnsURL: String(""), OwnerURL: String(""), Name: String(""), Body: String(""), Number: Int(0), State: String(""), CreatedAt: &Timestamp{}, UpdatedAt: &Timestamp{}, NodeID: String(""), Creator: &User{}, } want := `github.Project{ID:0, URL:"", HTMLURL:"", ColumnsURL:"", OwnerURL:"", Name:"", Body:"", Number:0, State:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, NodeID:"", Creator:github.User{}}` if got := v.String(); got != want { t.Errorf("Project.String = %v, want %v", got, want) } } func TestPullRequest_String(t *testing.T) { v := PullRequest{ ID: Int64(0), Number: Int(0), State: String(""), Locked: Bool(false), Title: String(""), Body: String(""), User: &User{}, Draft: Bool(false), Merged: Bool(false), Mergeable: Bool(false), MergeableState: String(""), MergedBy: &User{}, MergeCommitSHA: String(""), Rebaseable: Bool(false), Comments: Int(0), Commits: Int(0), Additions: Int(0), Deletions: Int(0), ChangedFiles: Int(0), URL: String(""), HTMLURL: String(""), IssueURL: String(""), StatusesURL: String(""), DiffURL: String(""), PatchURL: String(""), CommitsURL: String(""), CommentsURL: String(""), ReviewCommentsURL: String(""), ReviewCommentURL: String(""), ReviewComments: Int(0), Assignee: &User{}, Milestone: &Milestone{}, MaintainerCanModify: Bool(false), AuthorAssociation: String(""), NodeID: String(""), Links: &PRLinks{}, Head: &PullRequestBranch{}, Base: &PullRequestBranch{}, ActiveLockReason: String(""), } want := `github.PullRequest{ID:0, Number:0, State:"", Locked:false, Title:"", Body:"", User:github.User{}, Draft:false, Merged:false, Mergeable:false, MergeableState:"", MergedBy:github.User{}, MergeCommitSHA:"", Rebaseable:false, Comments:0, Commits:0, Additions:0, Deletions:0, ChangedFiles:0, URL:"", HTMLURL:"", IssueURL:"", StatusesURL:"", DiffURL:"", PatchURL:"", CommitsURL:"", CommentsURL:"", ReviewCommentsURL:"", ReviewCommentURL:"", ReviewComments:0, Assignee:github.User{}, Milestone:github.Milestone{}, MaintainerCanModify:false, AuthorAssociation:"", NodeID:"", Links:github.PRLinks{}, Head:github.PullRequestBranch{}, Base:github.PullRequestBranch{}, ActiveLockReason:""}` if got := v.String(); got != want { t.Errorf("PullRequest.String = %v, want %v", got, want) } } func TestPullRequestComment_String(t *testing.T) { v := PullRequestComment{ ID: Int64(0), NodeID: String(""), InReplyTo: Int64(0), Body: String(""), Path: String(""), DiffHunk: String(""), PullRequestReviewID: Int64(0), Position: Int(0), OriginalPosition: Int(0), CommitID: String(""), OriginalCommitID: String(""), User: &User{}, Reactions: &Reactions{}, AuthorAssociation: String(""), URL: String(""), HTMLURL: String(""), PullRequestURL: String(""), } want := `github.PullRequestComment{ID:0, NodeID:"", InReplyTo:0, Body:"", Path:"", DiffHunk:"", PullRequestReviewID:0, Position:0, OriginalPosition:0, CommitID:"", OriginalCommitID:"", User:github.User{}, Reactions:github.Reactions{}, AuthorAssociation:"", URL:"", HTMLURL:"", PullRequestURL:""}` if got := v.String(); got != want { t.Errorf("PullRequestComment.String = %v, want %v", got, want) } } func TestPullRequestReview_String(t *testing.T) { v := PullRequestReview{ ID: Int64(0), NodeID: String(""), User: &User{}, Body: String(""), CommitID: String(""), HTMLURL: String(""), PullRequestURL: String(""), State: String(""), } want := `github.PullRequestReview{ID:0, NodeID:"", User:github.User{}, Body:"", CommitID:"", HTMLURL:"", PullRequestURL:"", State:""}` if got := v.String(); got != want { t.Errorf("PullRequestReview.String = %v, want %v", got, want) } } func TestPullRequestReviewDismissalRequest_String(t *testing.T) { v := PullRequestReviewDismissalRequest{ Message: String(""), } want := `github.PullRequestReviewDismissalRequest{Message:""}` if got := v.String(); got != want { t.Errorf("PullRequestReviewDismissalRequest.String = %v, want %v", got, want) } } func TestPullRequestReviewRequest_String(t *testing.T) { v := PullRequestReviewRequest{ NodeID: String(""), CommitID: String(""), Body: String(""), Event: String(""), } want := `github.PullRequestReviewRequest{NodeID:"", CommitID:"", Body:"", Event:""}` if got := v.String(); got != want { t.Errorf("PullRequestReviewRequest.String = %v, want %v", got, want) } } func TestPullStats_String(t *testing.T) { v := PullStats{ TotalPulls: Int(0), MergedPulls: Int(0), MergablePulls: Int(0), UnmergablePulls: Int(0), } want := `github.PullStats{TotalPulls:0, MergedPulls:0, MergablePulls:0, UnmergablePulls:0}` if got := v.String(); got != want { t.Errorf("PullStats.String = %v, want %v", got, want) } } func TestPushEvent_String(t *testing.T) { v := PushEvent{ PushID: Int64(0), Head: String(""), Ref: String(""), Size: Int(0), Before: String(""), DistinctSize: Int(0), After: String(""), Created: Bool(false), Deleted: Bool(false), Forced: Bool(false), BaseRef: String(""), Compare: String(""), Repo: &PushEventRepository{}, HeadCommit: &PushEventCommit{}, Pusher: &User{}, Sender: &User{}, Installation: &Installation{}, } want := `github.PushEvent{PushID:0, Head:"", Ref:"", Size:0, Before:"", DistinctSize:0, After:"", Created:false, Deleted:false, Forced:false, BaseRef:"", Compare:"", Repo:github.PushEventRepository{}, HeadCommit:github.PushEventCommit{}, Pusher:github.User{}, Sender:github.User{}, Installation:github.Installation{}}` if got := v.String(); got != want { t.Errorf("PushEvent.String = %v, want %v", got, want) } } func TestPushEventCommit_String(t *testing.T) { v := PushEventCommit{ Message: String(""), Author: &CommitAuthor{}, URL: String(""), Distinct: Bool(false), SHA: String(""), ID: String(""), TreeID: String(""), Timestamp: &Timestamp{}, Committer: &CommitAuthor{}, } want := `github.PushEventCommit{Message:"", Author:github.CommitAuthor{}, URL:"", Distinct:false, SHA:"", ID:"", TreeID:"", Timestamp:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, Committer:github.CommitAuthor{}}` if got := v.String(); got != want { t.Errorf("PushEventCommit.String = %v, want %v", got, want) } } func TestRate_String(t *testing.T) { v := Rate{ Limit: 0, Remaining: 0, Reset: Timestamp{}, } want := `github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}` if got := v.String(); got != want { t.Errorf("Rate.String = %v, want %v", got, want) } } func TestReaction_String(t *testing.T) { v := Reaction{ ID: Int64(0), User: &User{}, NodeID: String(""), Content: String(""), } want := `github.Reaction{ID:0, User:github.User{}, NodeID:"", Content:""}` if got := v.String(); got != want { t.Errorf("Reaction.String = %v, want %v", got, want) } } func TestReference_String(t *testing.T) { v := Reference{ Ref: String(""), URL: String(""), Object: &GitObject{}, NodeID: String(""), } want := `github.Reference{Ref:"", URL:"", Object:github.GitObject{}, NodeID:""}` if got := v.String(); got != want { t.Errorf("Reference.String = %v, want %v", got, want) } } func TestReleaseAsset_String(t *testing.T) { v := ReleaseAsset{ ID: Int64(0), URL: String(""), Name: String(""), Label: String(""), State: String(""), ContentType: String(""), Size: Int(0), DownloadCount: Int(0), CreatedAt: &Timestamp{}, UpdatedAt: &Timestamp{}, BrowserDownloadURL: String(""), Uploader: &User{}, NodeID: String(""), } want := `github.ReleaseAsset{ID:0, URL:"", Name:"", Label:"", State:"", ContentType:"", Size:0, DownloadCount:0, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, BrowserDownloadURL:"", Uploader:github.User{}, NodeID:""}` if got := v.String(); got != want { t.Errorf("ReleaseAsset.String = %v, want %v", got, want) } } func TestRename_String(t *testing.T) { v := Rename{ From: String(""), To: String(""), } want := `github.Rename{From:"", To:""}` if got := v.String(); got != want { t.Errorf("Rename.String = %v, want %v", got, want) } } func TestRepoStats_String(t *testing.T) { v := RepoStats{ TotalRepos: Int(0), RootRepos: Int(0), ForkRepos: Int(0), OrgRepos: Int(0), TotalPushes: Int(0), TotalWikis: Int(0), } want := `github.RepoStats{TotalRepos:0, RootRepos:0, ForkRepos:0, OrgRepos:0, TotalPushes:0, TotalWikis:0}` if got := v.String(); got != want { t.Errorf("RepoStats.String = %v, want %v", got, want) } } func TestRepoStatus_String(t *testing.T) { v := RepoStatus{ ID: Int64(0), NodeID: String(""), URL: String(""), State: String(""), TargetURL: String(""), Description: String(""), Context: String(""), Creator: &User{}, } want := `github.RepoStatus{ID:0, NodeID:"", URL:"", State:"", TargetURL:"", Description:"", Context:"", Creator:github.User{}}` if got := v.String(); got != want { t.Errorf("RepoStatus.String = %v, want %v", got, want) } } func TestRepository_String(t *testing.T) { v := Repository{ ID: Int64(0), NodeID: String(""), Owner: &User{}, Name: String(""), FullName: String(""), Description: String(""), Homepage: String(""), CodeOfConduct: &CodeOfConduct{}, DefaultBranch: String(""), MasterBranch: String(""), CreatedAt: &Timestamp{}, PushedAt: &Timestamp{}, UpdatedAt: &Timestamp{}, HTMLURL: String(""), CloneURL: String(""), GitURL: String(""), MirrorURL: String(""), SSHURL: String(""), SVNURL: String(""), Language: String(""), Fork: Bool(false), ForksCount: Int(0), NetworkCount: Int(0), OpenIssuesCount: Int(0), StargazersCount: Int(0), SubscribersCount: Int(0), WatchersCount: Int(0), Size: Int(0), AutoInit: Bool(false), Parent: &Repository{}, Source: &Repository{}, TemplateRepository: &Repository{}, Organization: &Organization{}, AllowRebaseMerge: Bool(false), AllowSquashMerge: Bool(false), AllowMergeCommit: Bool(false), Archived: Bool(false), Disabled: Bool(false), License: &License{}, Private: Bool(false), HasIssues: Bool(false), HasWiki: Bool(false), HasPages: Bool(false), HasProjects: Bool(false), HasDownloads: Bool(false), IsTemplate: Bool(false), LicenseTemplate: String(""), GitignoreTemplate: String(""), TeamID: Int64(0), URL: String(""), ArchiveURL: String(""), AssigneesURL: String(""), BlobsURL: String(""), BranchesURL: String(""), CollaboratorsURL: String(""), CommentsURL: String(""), CommitsURL: String(""), CompareURL: String(""), ContentsURL: String(""), ContributorsURL: String(""), DeploymentsURL: String(""), DownloadsURL: String(""), EventsURL: String(""), ForksURL: String(""), GitCommitsURL: String(""), GitRefsURL: String(""), GitTagsURL: String(""), HooksURL: String(""), IssueCommentURL: String(""), IssueEventsURL: String(""), IssuesURL: String(""), KeysURL: String(""), LabelsURL: String(""), LanguagesURL: String(""), MergesURL: String(""), MilestonesURL: String(""), NotificationsURL: String(""), PullsURL: String(""), ReleasesURL: String(""), StargazersURL: String(""), StatusesURL: String(""), SubscribersURL: String(""), SubscriptionURL: String(""), TagsURL: String(""), TreesURL: String(""), TeamsURL: String(""), } want := `github.Repository{ID:0, NodeID:"", Owner:github.User{}, Name:"", FullName:"", Description:"", Homepage:"", CodeOfConduct:github.CodeOfConduct{}, DefaultBranch:"", MasterBranch:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, PushedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, HTMLURL:"", CloneURL:"", GitURL:"", MirrorURL:"", SSHURL:"", SVNURL:"", Language:"", Fork:false, ForksCount:0, NetworkCount:0, OpenIssuesCount:0, StargazersCount:0, SubscribersCount:0, WatchersCount:0, Size:0, AutoInit:false, Parent:github.Repository{}, Source:github.Repository{}, TemplateRepository:github.Repository{}, Organization:github.Organization{}, AllowRebaseMerge:false, AllowSquashMerge:false, AllowMergeCommit:false, Archived:false, Disabled:false, License:github.License{}, Private:false, HasIssues:false, HasWiki:false, HasPages:false, HasProjects:false, HasDownloads:false, IsTemplate:false, LicenseTemplate:"", GitignoreTemplate:"", TeamID:0, URL:"", ArchiveURL:"", AssigneesURL:"", BlobsURL:"", BranchesURL:"", CollaboratorsURL:"", CommentsURL:"", CommitsURL:"", CompareURL:"", ContentsURL:"", ContributorsURL:"", DeploymentsURL:"", DownloadsURL:"", EventsURL:"", ForksURL:"", GitCommitsURL:"", GitRefsURL:"", GitTagsURL:"", HooksURL:"", IssueCommentURL:"", IssueEventsURL:"", IssuesURL:"", KeysURL:"", LabelsURL:"", LanguagesURL:"", MergesURL:"", MilestonesURL:"", NotificationsURL:"", PullsURL:"", ReleasesURL:"", StargazersURL:"", StatusesURL:"", SubscribersURL:"", SubscriptionURL:"", TagsURL:"", TreesURL:"", TeamsURL:""}` if got := v.String(); got != want { t.Errorf("Repository.String = %v, want %v", got, want) } } func TestRepositoryComment_String(t *testing.T) { v := RepositoryComment{ HTMLURL: String(""), URL: String(""), ID: Int64(0), NodeID: String(""), CommitID: String(""), User: &User{}, Reactions: &Reactions{}, Body: String(""), Path: String(""), Position: Int(0), } want := `github.RepositoryComment{HTMLURL:"", URL:"", ID:0, NodeID:"", CommitID:"", User:github.User{}, Reactions:github.Reactions{}, Body:"", Path:"", Position:0}` if got := v.String(); got != want { t.Errorf("RepositoryComment.String = %v, want %v", got, want) } } func TestRepositoryCommit_String(t *testing.T) { v := RepositoryCommit{ NodeID: String(""), SHA: String(""), Commit: &Commit{}, Author: &User{}, Committer: &User{}, HTMLURL: String(""), URL: String(""), CommentsURL: String(""), Stats: &CommitStats{}, } want := `github.RepositoryCommit{NodeID:"", SHA:"", Commit:github.Commit{}, Author:github.User{}, Committer:github.User{}, HTMLURL:"", URL:"", CommentsURL:"", Stats:github.CommitStats{}}` if got := v.String(); got != want { t.Errorf("RepositoryCommit.String = %v, want %v", got, want) } } func TestRepositoryContent_String(t *testing.T) { v := RepositoryContent{ Type: String(""), Target: String(""), Encoding: String(""), Size: Int(0), Name: String(""), Path: String(""), Content: String(""), SHA: String(""), URL: String(""), GitURL: String(""), HTMLURL: String(""), DownloadURL: String(""), } want := `github.RepositoryContent{Type:"", Target:"", Encoding:"", Size:0, Name:"", Path:"", Content:"", SHA:"", URL:"", GitURL:"", HTMLURL:"", DownloadURL:""}` if got := v.String(); got != want { t.Errorf("RepositoryContent.String = %v, want %v", got, want) } } func TestRepositoryLicense_String(t *testing.T) { v := RepositoryLicense{ Name: String(""), Path: String(""), SHA: String(""), Size: Int(0), URL: String(""), HTMLURL: String(""), GitURL: String(""), DownloadURL: String(""), Type: String(""), Content: String(""), Encoding: String(""), License: &License{}, } want := `github.RepositoryLicense{Name:"", Path:"", SHA:"", Size:0, URL:"", HTMLURL:"", GitURL:"", DownloadURL:"", Type:"", Content:"", Encoding:"", License:github.License{}}` if got := v.String(); got != want { t.Errorf("RepositoryLicense.String = %v, want %v", got, want) } } func TestRepositoryRelease_String(t *testing.T) { v := RepositoryRelease{ TagName: String(""), TargetCommitish: String(""), Name: String(""), Body: String(""), Draft: Bool(false), Prerelease: Bool(false), ID: Int64(0), CreatedAt: &Timestamp{}, PublishedAt: &Timestamp{}, URL: String(""), HTMLURL: String(""), AssetsURL: String(""), UploadURL: String(""), ZipballURL: String(""), TarballURL: String(""), Author: &User{}, NodeID: String(""), } want := `github.RepositoryRelease{TagName:"", TargetCommitish:"", Name:"", Body:"", Draft:false, Prerelease:false, ID:0, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, PublishedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, URL:"", HTMLURL:"", AssetsURL:"", UploadURL:"", ZipballURL:"", TarballURL:"", Author:github.User{}, NodeID:""}` if got := v.String(); got != want { t.Errorf("RepositoryRelease.String = %v, want %v", got, want) } } func TestSourceImportAuthor_String(t *testing.T) { v := SourceImportAuthor{ ID: Int64(0), RemoteID: String(""), RemoteName: String(""), Email: String(""), Name: String(""), URL: String(""), ImportURL: String(""), } want := `github.SourceImportAuthor{ID:0, RemoteID:"", RemoteName:"", Email:"", Name:"", URL:"", ImportURL:""}` if got := v.String(); got != want { t.Errorf("SourceImportAuthor.String = %v, want %v", got, want) } } func TestTeam_String(t *testing.T) { v := Team{ ID: Int64(0), NodeID: String(""), Name: String(""), Description: String(""), URL: String(""), Slug: String(""), Permission: String(""), Privacy: String(""), MembersCount: Int(0), ReposCount: Int(0), Organization: &Organization{}, MembersURL: String(""), RepositoriesURL: String(""), Parent: &Team{}, LDAPDN: String(""), } want := `github.Team{ID:0, NodeID:"", Name:"", Description:"", URL:"", Slug:"", Permission:"", Privacy:"", MembersCount:0, ReposCount:0, Organization:github.Organization{}, MembersURL:"", RepositoriesURL:"", Parent:github.Team{}, LDAPDN:""}` if got := v.String(); got != want { t.Errorf("Team.String = %v, want %v", got, want) } } func TestTeamDiscussion_String(t *testing.T) { v := TeamDiscussion{ Author: &User{}, Body: String(""), BodyHTML: String(""), BodyVersion: String(""), CommentsCount: Int(0), CommentsURL: String(""), CreatedAt: &Timestamp{}, LastEditedAt: &Timestamp{}, HTMLURL: String(""), NodeID: String(""), Number: Int(0), Pinned: Bool(false), Private: Bool(false), TeamURL: String(""), Title: String(""), UpdatedAt: &Timestamp{}, URL: String(""), Reactions: &Reactions{}, } want := `github.TeamDiscussion{Author:github.User{}, Body:"", BodyHTML:"", BodyVersion:"", CommentsCount:0, CommentsURL:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, LastEditedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, HTMLURL:"", NodeID:"", Number:0, Pinned:false, Private:false, TeamURL:"", Title:"", UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, URL:"", Reactions:github.Reactions{}}` if got := v.String(); got != want { t.Errorf("TeamDiscussion.String = %v, want %v", got, want) } } func TestTeamLDAPMapping_String(t *testing.T) { v := TeamLDAPMapping{ ID: Int64(0), LDAPDN: String(""), URL: String(""), Name: String(""), Slug: String(""), Description: String(""), Privacy: String(""), Permission: String(""), MembersURL: String(""), RepositoriesURL: String(""), } want := `github.TeamLDAPMapping{ID:0, LDAPDN:"", URL:"", Name:"", Slug:"", Description:"", Privacy:"", Permission:"", MembersURL:"", RepositoriesURL:""}` if got := v.String(); got != want { t.Errorf("TeamLDAPMapping.String = %v, want %v", got, want) } } func TestTextMatch_String(t *testing.T) { v := TextMatch{ ObjectURL: String(""), ObjectType: String(""), Property: String(""), Fragment: String(""), } want := `github.TextMatch{ObjectURL:"", ObjectType:"", Property:"", Fragment:""}` if got := v.String(); got != want { t.Errorf("TextMatch.String = %v, want %v", got, want) } } func TestTree_String(t *testing.T) { v := Tree{ SHA: String(""), Truncated: Bool(false), } want := `github.Tree{SHA:"", Truncated:false}` if got := v.String(); got != want { t.Errorf("Tree.String = %v, want %v", got, want) } } func TestTreeEntry_String(t *testing.T) { v := TreeEntry{ SHA: String(""), Path: String(""), Mode: String(""), Type: String(""), Size: Int(0), Content: String(""), URL: String(""), } want := `github.TreeEntry{SHA:"", Path:"", Mode:"", Type:"", Size:0, Content:"", URL:""}` if got := v.String(); got != want { t.Errorf("TreeEntry.String = %v, want %v", got, want) } } func TestUser_String(t *testing.T) { v := User{ Login: String(""), ID: Int64(0), NodeID: String(""), AvatarURL: String(""), HTMLURL: String(""), GravatarID: String(""), Name: String(""), Company: String(""), Blog: String(""), Location: String(""), Email: String(""), Hireable: Bool(false), Bio: String(""), PublicRepos: Int(0), PublicGists: Int(0), Followers: Int(0), Following: Int(0), CreatedAt: &Timestamp{}, UpdatedAt: &Timestamp{}, SuspendedAt: &Timestamp{}, Type: String(""), SiteAdmin: Bool(false), TotalPrivateRepos: Int(0), OwnedPrivateRepos: Int(0), PrivateGists: Int(0), DiskUsage: Int(0), Collaborators: Int(0), TwoFactorAuthentication: Bool(false), Plan: &Plan{}, LdapDn: String(""), URL: String(""), EventsURL: String(""), FollowingURL: String(""), FollowersURL: String(""), GistsURL: String(""), OrganizationsURL: String(""), ReceivedEventsURL: String(""), ReposURL: String(""), StarredURL: String(""), SubscriptionsURL: String(""), } want := `github.User{Login:"", ID:0, NodeID:"", AvatarURL:"", HTMLURL:"", GravatarID:"", Name:"", Company:"", Blog:"", Location:"", Email:"", Hireable:false, Bio:"", PublicRepos:0, PublicGists:0, Followers:0, Following:0, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, SuspendedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, Type:"", SiteAdmin:false, TotalPrivateRepos:0, OwnedPrivateRepos:0, PrivateGists:0, DiskUsage:0, Collaborators:0, TwoFactorAuthentication:false, Plan:github.Plan{}, LdapDn:"", URL:"", EventsURL:"", FollowingURL:"", FollowersURL:"", GistsURL:"", OrganizationsURL:"", ReceivedEventsURL:"", ReposURL:"", StarredURL:"", SubscriptionsURL:""}` if got := v.String(); got != want { t.Errorf("User.String = %v, want %v", got, want) } } func TestUserLDAPMapping_String(t *testing.T) { v := UserLDAPMapping{ ID: Int64(0), LDAPDN: String(""), Login: String(""), AvatarURL: String(""), GravatarID: String(""), Type: String(""), SiteAdmin: Bool(false), URL: String(""), EventsURL: String(""), FollowingURL: String(""), FollowersURL: String(""), GistsURL: String(""), OrganizationsURL: String(""), ReceivedEventsURL: String(""), ReposURL: String(""), StarredURL: String(""), SubscriptionsURL: String(""), } want := `github.UserLDAPMapping{ID:0, LDAPDN:"", Login:"", AvatarURL:"", GravatarID:"", Type:"", SiteAdmin:false, URL:"", EventsURL:"", FollowingURL:"", FollowersURL:"", GistsURL:"", OrganizationsURL:"", ReceivedEventsURL:"", ReposURL:"", StarredURL:"", SubscriptionsURL:""}` if got := v.String(); got != want { t.Errorf("UserLDAPMapping.String = %v, want %v", got, want) } } func TestUserMigration_String(t *testing.T) { v := UserMigration{ ID: Int64(0), GUID: String(""), State: String(""), LockRepositories: Bool(false), ExcludeAttachments: Bool(false), URL: String(""), CreatedAt: String(""), UpdatedAt: String(""), } want := `github.UserMigration{ID:0, GUID:"", State:"", LockRepositories:false, ExcludeAttachments:false, URL:"", CreatedAt:"", UpdatedAt:""}` if got := v.String(); got != want { t.Errorf("UserMigration.String = %v, want %v", got, want) } } func TestUserStats_String(t *testing.T) { v := UserStats{ TotalUsers: Int(0), AdminUsers: Int(0), SuspendedUsers: Int(0), } want := `github.UserStats{TotalUsers:0, AdminUsers:0, SuspendedUsers:0}` if got := v.String(); got != want { t.Errorf("UserStats.String = %v, want %v", got, want) } } func TestWebHookAuthor_String(t *testing.T) { v := WebHookAuthor{ Email: String(""), Name: String(""), Username: String(""), } want := `github.WebHookAuthor{Email:"", Name:"", Username:""}` if got := v.String(); got != want { t.Errorf("WebHookAuthor.String = %v, want %v", got, want) } } func TestWebHookCommit_String(t *testing.T) { v := WebHookCommit{ Author: &WebHookAuthor{}, Committer: &WebHookAuthor{}, Distinct: Bool(false), ID: String(""), Message: String(""), } want := `github.WebHookCommit{Author:github.WebHookAuthor{}, Committer:github.WebHookAuthor{}, Distinct:false, ID:"", Message:""}` if got := v.String(); got != want { t.Errorf("WebHookCommit.String = %v, want %v", got, want) } } func TestWebHookPayload_String(t *testing.T) { v := WebHookPayload{ After: String(""), Before: String(""), Compare: String(""), Created: Bool(false), Deleted: Bool(false), Forced: Bool(false), HeadCommit: &WebHookCommit{}, Pusher: &User{}, Ref: String(""), Repo: &Repository{}, Sender: &User{}, } want := `github.WebHookPayload{After:"", Before:"", Compare:"", Created:false, Deleted:false, Forced:false, HeadCommit:github.WebHookCommit{}, Pusher:github.User{}, Ref:"", Repo:github.Repository{}, Sender:github.User{}}` if got := v.String(); got != want { t.Errorf("WebHookPayload.String = %v, want %v", got, want) } } func TestWeeklyCommitActivity_String(t *testing.T) { v := WeeklyCommitActivity{ Total: Int(0), Week: &Timestamp{}, } want := `github.WeeklyCommitActivity{Total:0, Week:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}` if got := v.String(); got != want { t.Errorf("WeeklyCommitActivity.String = %v, want %v", got, want) } } func TestWeeklyStats_String(t *testing.T) { v := WeeklyStats{ Week: &Timestamp{}, Additions: Int(0), Deletions: Int(0), Commits: Int(0), } want := `github.WeeklyStats{Week:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, Additions:0, Deletions:0, Commits:0}` if got := v.String(); got != want { t.Errorf("WeeklyStats.String = %v, want %v", got, want) } } go-github-28.1.1/github/github.go000066400000000000000000001062361353501270500165740ustar00rootroot00000000000000// 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. //go:generate go run gen-accessors.go //go:generate go run gen-stringify-test.go package github import ( "bytes" "context" "encoding/json" "errors" "fmt" "io" "io/ioutil" "net/http" "net/url" "reflect" "strconv" "strings" "sync" "time" "github.com/google/go-querystring/query" ) const ( defaultBaseURL = "https://api.github.com/" uploadBaseURL = "https://uploads.github.com/" userAgent = "go-github" headerRateLimit = "X-RateLimit-Limit" headerRateRemaining = "X-RateLimit-Remaining" headerRateReset = "X-RateLimit-Reset" headerOTP = "X-GitHub-OTP" mediaTypeV3 = "application/vnd.github.v3+json" defaultMediaType = "application/octet-stream" mediaTypeV3SHA = "application/vnd.github.v3.sha" mediaTypeV3Diff = "application/vnd.github.v3.diff" mediaTypeV3Patch = "application/vnd.github.v3.patch" mediaTypeOrgPermissionRepo = "application/vnd.github.v3.repository+json" // Media Type values to access preview APIs // https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/ mediaTypeStarringPreview = "application/vnd.github.v3.star+json" // https://help.github.com/enterprise/2.4/admin/guides/migrations/exporting-the-github-com-organization-s-repositories/ mediaTypeMigrationsPreview = "application/vnd.github.wyandotte-preview+json" // https://developer.github.com/changes/2016-04-06-deployment-and-deployment-status-enhancements/ mediaTypeDeploymentStatusPreview = "application/vnd.github.ant-man-preview+json" // https://developer.github.com/changes/2018-10-16-deployments-environments-states-and-auto-inactive-updates/ mediaTypeExpandDeploymentStatusPreview = "application/vnd.github.flash-preview+json" // https://developer.github.com/changes/2016-02-19-source-import-preview-api/ mediaTypeImportPreview = "application/vnd.github.barred-rock-preview" // https://developer.github.com/changes/2016-05-12-reactions-api-preview/ mediaTypeReactionsPreview = "application/vnd.github.squirrel-girl-preview" // https://developer.github.com/changes/2016-05-23-timeline-preview-api/ mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json" // https://developer.github.com/changes/2016-07-06-github-pages-preiew-api/ mediaTypePagesPreview = "application/vnd.github.mister-fantastic-preview+json" // https://developer.github.com/changes/2016-09-14-projects-api/ mediaTypeProjectsPreview = "application/vnd.github.inertia-preview+json" // https://developer.github.com/changes/2016-09-14-Integrations-Early-Access/ mediaTypeIntegrationPreview = "application/vnd.github.machine-man-preview+json" // https://developer.github.com/changes/2017-01-05-commit-search-api/ mediaTypeCommitSearchPreview = "application/vnd.github.cloak-preview+json" // https://developer.github.com/changes/2017-02-28-user-blocking-apis-and-webhook/ mediaTypeBlockUsersPreview = "application/vnd.github.giant-sentry-fist-preview+json" // https://developer.github.com/changes/2017-02-09-community-health/ mediaTypeRepositoryCommunityHealthMetricsPreview = "application/vnd.github.black-panther-preview+json" // https://developer.github.com/changes/2017-05-23-coc-api/ mediaTypeCodesOfConductPreview = "application/vnd.github.scarlet-witch-preview+json" // https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/ mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json" // https://developer.github.com/changes/2017-08-30-preview-nested-teams/ mediaTypeNestedTeamsPreview = "application/vnd.github.hellcat-preview+json" // https://developer.github.com/changes/2017-11-09-repository-transfer-api-preview/ mediaTypeRepositoryTransferPreview = "application/vnd.github.nightshade-preview+json" // https://developer.github.com/changes/2018-01-25-organization-invitation-api-preview/ mediaTypeOrganizationInvitationPreview = "application/vnd.github.dazzler-preview+json" // https://developer.github.com/changes/2018-03-16-protected-branches-required-approving-reviews/ mediaTypeRequiredApprovingReviewsPreview = "application/vnd.github.luke-cage-preview+json" // https://developer.github.com/changes/2018-02-22-label-description-search-preview/ mediaTypeLabelDescriptionSearchPreview = "application/vnd.github.symmetra-preview+json" // https://developer.github.com/changes/2018-02-07-team-discussions-api/ mediaTypeTeamDiscussionsPreview = "application/vnd.github.echo-preview+json" // https://developer.github.com/changes/2018-03-21-hovercard-api-preview/ mediaTypeHovercardPreview = "application/vnd.github.hagar-preview+json" // https://developer.github.com/changes/2018-01-10-lock-reason-api-preview/ mediaTypeLockReasonPreview = "application/vnd.github.sailor-v-preview+json" // https://developer.github.com/changes/2018-05-07-new-checks-api-public-beta/ mediaTypeCheckRunsPreview = "application/vnd.github.antiope-preview+json" // https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/ mediaTypePreReceiveHooksPreview = "application/vnd.github.eye-scream-preview" // https://developer.github.com/changes/2018-02-22-protected-branches-required-signatures/ mediaTypeSignaturePreview = "application/vnd.github.zzzax-preview+json" // https://developer.github.com/changes/2018-09-05-project-card-events/ mediaTypeProjectCardDetailsPreview = "application/vnd.github.starfox-preview+json" // https://developer.github.com/changes/2018-12-18-interactions-preview/ mediaTypeInteractionRestrictionsPreview = "application/vnd.github.sombra-preview+json" // https://developer.github.com/changes/2019-02-14-draft-pull-requests/ mediaTypeDraftPreview = "application/vnd.github.shadow-cat-preview+json" // https://developer.github.com/changes/2019-03-14-enabling-disabling-pages/ mediaTypeEnablePagesAPIPreview = "application/vnd.github.switcheroo-preview+json" // https://developer.github.com/changes/2019-04-24-vulnerability-alerts/ mediaTypeRequiredVulnerabilityAlertsPreview = "application/vnd.github.dorian-preview+json" // https://developer.github.com/changes/2019-06-04-automated-security-fixes/ mediaTypeRequiredAutomatedSecurityFixesPreview = "application/vnd.github.london-preview+json" // https://developer.github.com/changes/2019-05-29-update-branch-api/ mediaTypeUpdatePullRequestBranchPreview = "application/vnd.github.lydian-preview+json" // https://developer.github.com/changes/2019-04-11-pulls-branches-for-commit/ mediaTypeListPullsOrBranchesForCommitPreview = "application/vnd.github.groot-preview+json" // https://developer.github.com/changes/2019-06-12-team-sync/ mediaTypeTeamSyncPreview = "application/vnd.github.team-sync-preview+json" // https://developer.github.com/v3/previews/#repository-creation-permissions mediaTypeMemberAllowedRepoCreationTypePreview = "application/vnd.github.surtur-preview+json" // https://developer.github.com/v3/previews/#create-and-use-repository-templates mediaTypeRepositoryTemplatePreview = "application/vnd.github.baptiste-preview+json" ) // A Client manages communication with the GitHub API. type Client struct { clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func. client *http.Client // HTTP client used to communicate with the API. // Base URL for API requests. Defaults to the public GitHub API, but can be // set to a domain endpoint to use with GitHub Enterprise. BaseURL should // always be specified with a trailing slash. BaseURL *url.URL // Base URL for uploading files. UploadURL *url.URL // User agent used when communicating with the GitHub API. UserAgent string rateMu sync.Mutex rateLimits [categories]Rate // Rate limits for the client as determined by the most recent API calls. common service // Reuse a single struct instead of allocating one for each service on the heap. // Services used for talking to different parts of the GitHub API. Activity *ActivityService Admin *AdminService Apps *AppsService Authorizations *AuthorizationsService Checks *ChecksService Gists *GistsService Git *GitService Gitignores *GitignoresService Interactions *InteractionsService Issues *IssuesService Licenses *LicensesService Marketplace *MarketplaceService Migrations *MigrationService Organizations *OrganizationsService Projects *ProjectsService PullRequests *PullRequestsService Reactions *ReactionsService Repositories *RepositoriesService Search *SearchService Teams *TeamsService Users *UsersService } type service struct { client *Client } // ListOptions specifies the optional parameters to various List methods that // support pagination. type ListOptions struct { // For paginated result sets, page of results to retrieve. Page int `url:"page,omitempty"` // For paginated result sets, the number of results to include per page. PerPage int `url:"per_page,omitempty"` } // UploadOptions specifies the parameters to methods that support uploads. type UploadOptions struct { Name string `url:"name,omitempty"` Label string `url:"label,omitempty"` MediaType string `url:"-"` } // RawType represents type of raw format of a request instead of JSON. type RawType uint8 const ( // Diff format. Diff RawType = 1 + iota // Patch format. Patch ) // RawOptions specifies parameters when user wants to get raw format of // a response instead of JSON. type RawOptions struct { Type RawType } // addOptions adds the parameters in opt as URL query parameters to s. opt // must be a struct whose fields may contain "url" tags. func addOptions(s string, opt interface{}) (string, error) { v := reflect.ValueOf(opt) if v.Kind() == reflect.Ptr && v.IsNil() { return s, nil } u, err := url.Parse(s) if err != nil { return s, err } qs, err := query.Values(opt) if err != nil { return s, err } u.RawQuery = qs.Encode() return u.String(), nil } // NewClient returns a new GitHub API client. If a nil httpClient is // provided, a new http.Client will be used. To use API methods which require // authentication, provide an http.Client that will perform the authentication // for you (such as that provided by the golang.org/x/oauth2 library). func NewClient(httpClient *http.Client) *Client { if httpClient == nil { httpClient = &http.Client{} } baseURL, _ := url.Parse(defaultBaseURL) uploadURL, _ := url.Parse(uploadBaseURL) c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent, UploadURL: uploadURL} c.common.client = c c.Activity = (*ActivityService)(&c.common) c.Admin = (*AdminService)(&c.common) c.Apps = (*AppsService)(&c.common) c.Authorizations = (*AuthorizationsService)(&c.common) c.Checks = (*ChecksService)(&c.common) c.Gists = (*GistsService)(&c.common) c.Git = (*GitService)(&c.common) c.Gitignores = (*GitignoresService)(&c.common) c.Interactions = (*InteractionsService)(&c.common) c.Issues = (*IssuesService)(&c.common) c.Licenses = (*LicensesService)(&c.common) c.Marketplace = &MarketplaceService{client: c} c.Migrations = (*MigrationService)(&c.common) c.Organizations = (*OrganizationsService)(&c.common) c.Projects = (*ProjectsService)(&c.common) c.PullRequests = (*PullRequestsService)(&c.common) c.Reactions = (*ReactionsService)(&c.common) c.Repositories = (*RepositoriesService)(&c.common) c.Search = (*SearchService)(&c.common) c.Teams = (*TeamsService)(&c.common) c.Users = (*UsersService)(&c.common) return c } // NewEnterpriseClient returns a new GitHub API client with provided // base URL and upload URL (often the same URL). // If either URL does not have a trailing slash, one is added automatically. // If a nil httpClient is provided, a new http.Client will be used. // // Note that NewEnterpriseClient is a convenience helper only; // its behavior is equivalent to using NewClient, followed by setting // the BaseURL and UploadURL fields. func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*Client, error) { baseEndpoint, err := url.Parse(baseURL) if err != nil { return nil, err } if !strings.HasSuffix(baseEndpoint.Path, "/") { baseEndpoint.Path += "/" } uploadEndpoint, err := url.Parse(uploadURL) if err != nil { return nil, err } if !strings.HasSuffix(uploadEndpoint.Path, "/") { uploadEndpoint.Path += "/" } c := NewClient(httpClient) c.BaseURL = baseEndpoint c.UploadURL = uploadEndpoint return c, nil } // NewRequest creates an API request. A relative URL can be provided in urlStr, // in which case it is resolved relative to the BaseURL of the Client. // Relative URLs should always be specified without a preceding slash. If // specified, the value pointed to by body is JSON encoded and included as the // request body. func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) { if !strings.HasSuffix(c.BaseURL.Path, "/") { return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL) } u, err := c.BaseURL.Parse(urlStr) if err != nil { return nil, err } var buf io.ReadWriter if body != nil { buf = new(bytes.Buffer) enc := json.NewEncoder(buf) enc.SetEscapeHTML(false) err := enc.Encode(body) if err != nil { return nil, err } } req, err := http.NewRequest(method, u.String(), buf) if err != nil { return nil, err } if body != nil { req.Header.Set("Content-Type", "application/json") } req.Header.Set("Accept", mediaTypeV3) if c.UserAgent != "" { req.Header.Set("User-Agent", c.UserAgent) } return req, nil } // NewUploadRequest creates an upload request. A relative URL can be provided in // urlStr, in which case it is resolved relative to the UploadURL of the Client. // Relative URLs should always be specified without a preceding slash. func (c *Client) NewUploadRequest(urlStr string, reader io.Reader, size int64, mediaType string) (*http.Request, error) { if !strings.HasSuffix(c.UploadURL.Path, "/") { return nil, fmt.Errorf("UploadURL must have a trailing slash, but %q does not", c.UploadURL) } u, err := c.UploadURL.Parse(urlStr) if err != nil { return nil, err } req, err := http.NewRequest("POST", u.String(), reader) if err != nil { return nil, err } req.ContentLength = size if mediaType == "" { mediaType = defaultMediaType } req.Header.Set("Content-Type", mediaType) req.Header.Set("Accept", mediaTypeV3) req.Header.Set("User-Agent", c.UserAgent) return req, nil } // Response is a GitHub API response. This wraps the standard http.Response // returned from GitHub and provides convenient access to things like // pagination links. type Response struct { *http.Response // These fields provide the page values for paginating through a set of // results. Any or all of these may be set to the zero value for // responses that are not part of a paginated set, or for which there // are no additional pages. NextPage int PrevPage int FirstPage int LastPage int // Explicitly specify the Rate type so Rate's String() receiver doesn't // propagate to Response. Rate Rate } // newResponse creates a new Response for the provided http.Response. // r must not be nil. func newResponse(r *http.Response) *Response { response := &Response{Response: r} response.populatePageValues() response.Rate = parseRate(r) return response } // populatePageValues parses the HTTP Link response headers and populates the // various pagination link values in the Response. func (r *Response) populatePageValues() { if links, ok := r.Response.Header["Link"]; ok && len(links) > 0 { for _, link := range strings.Split(links[0], ",") { segments := strings.Split(strings.TrimSpace(link), ";") // link must at least have href and rel if len(segments) < 2 { continue } // ensure href is properly formatted if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") { continue } // try to pull out page parameter url, err := url.Parse(segments[0][1 : len(segments[0])-1]) if err != nil { continue } page := url.Query().Get("page") if page == "" { continue } for _, segment := range segments[1:] { switch strings.TrimSpace(segment) { case `rel="next"`: r.NextPage, _ = strconv.Atoi(page) case `rel="prev"`: r.PrevPage, _ = strconv.Atoi(page) case `rel="first"`: r.FirstPage, _ = strconv.Atoi(page) case `rel="last"`: r.LastPage, _ = strconv.Atoi(page) } } } } } // parseRate parses the rate related headers. func parseRate(r *http.Response) Rate { var rate Rate if limit := r.Header.Get(headerRateLimit); limit != "" { rate.Limit, _ = strconv.Atoi(limit) } if remaining := r.Header.Get(headerRateRemaining); remaining != "" { rate.Remaining, _ = strconv.Atoi(remaining) } if reset := r.Header.Get(headerRateReset); reset != "" { if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 { rate.Reset = Timestamp{time.Unix(v, 0)} } } return rate } // Do sends an API request and returns the API response. The API response is // JSON decoded and stored in the value pointed to by v, or returned as an // error if an API error has occurred. If v implements the io.Writer // interface, the raw response body will be written to v, without attempting to // first decode it. If rate limit is exceeded and reset time is in the future, // Do returns *RateLimitError immediately without making a network API call. // // The provided ctx must be non-nil. If it is canceled or times out, // ctx.Err() will be returned. func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) { req = withContext(ctx, req) rateLimitCategory := category(req.URL.Path) // If we've hit rate limit, don't make further requests before Reset time. if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil { return &Response{ Response: err.Response, Rate: err.Rate, }, err } resp, err := c.client.Do(req) if err != nil { // If we got an error, and the context has been canceled, // the context's error is probably more useful. select { case <-ctx.Done(): return nil, ctx.Err() default: } // If the error type is *url.Error, sanitize its URL before returning. if e, ok := err.(*url.Error); ok { if url, err := url.Parse(e.URL); err == nil { e.URL = sanitizeURL(url).String() return nil, e } } return nil, err } defer resp.Body.Close() response := newResponse(resp) c.rateMu.Lock() c.rateLimits[rateLimitCategory] = response.Rate c.rateMu.Unlock() err = CheckResponse(resp) if err != nil { // Special case for AcceptedErrors. If an AcceptedError // has been encountered, the response's payload will be // added to the AcceptedError and returned. // // Issue #1022 aerr, ok := err.(*AcceptedError) if ok { b, readErr := ioutil.ReadAll(resp.Body) if readErr != nil { return response, readErr } aerr.Raw = b return response, aerr } return response, err } if v != nil { if w, ok := v.(io.Writer); ok { io.Copy(w, resp.Body) } else { decErr := json.NewDecoder(resp.Body).Decode(v) if decErr == io.EOF { decErr = nil // ignore EOF errors caused by empty response body } if decErr != nil { err = decErr } } } return response, err } // checkRateLimitBeforeDo does not make any network calls, but uses existing knowledge from // current client state in order to quickly check if *RateLimitError can be immediately returned // from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily. // Otherwise it returns nil, and Client.Do should proceed normally. func (c *Client) checkRateLimitBeforeDo(req *http.Request, rateLimitCategory rateLimitCategory) *RateLimitError { c.rateMu.Lock() rate := c.rateLimits[rateLimitCategory] c.rateMu.Unlock() if !rate.Reset.Time.IsZero() && rate.Remaining == 0 && time.Now().Before(rate.Reset.Time) { // Create a fake response. resp := &http.Response{ Status: http.StatusText(http.StatusForbidden), StatusCode: http.StatusForbidden, Request: req, Header: make(http.Header), Body: ioutil.NopCloser(strings.NewReader("")), } return &RateLimitError{ Rate: rate, Response: resp, Message: fmt.Sprintf("API rate limit of %v still exceeded until %v, not making remote request.", rate.Limit, rate.Reset.Time), } } return nil } /* An ErrorResponse reports one or more errors caused by an API request. GitHub API docs: https://developer.github.com/v3/#client-errors */ type ErrorResponse struct { Response *http.Response // HTTP response that caused this error Message string `json:"message"` // error message Errors []Error `json:"errors"` // more detail on individual errors // Block is only populated on certain types of errors such as code 451. // See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/ // for more information. Block *struct { Reason string `json:"reason,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` } `json:"block,omitempty"` // Most errors will also include a documentation_url field pointing // to some content that might help you resolve the error, see // https://developer.github.com/v3/#client-errors DocumentationURL string `json:"documentation_url,omitempty"` } func (r *ErrorResponse) Error() string { return fmt.Sprintf("%v %v: %d %v %+v", r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), r.Response.StatusCode, r.Message, r.Errors) } // TwoFactorAuthError occurs when using HTTP Basic Authentication for a user // that has two-factor authentication enabled. The request can be reattempted // by providing a one-time password in the request. type TwoFactorAuthError ErrorResponse func (r *TwoFactorAuthError) Error() string { return (*ErrorResponse)(r).Error() } // RateLimitError occurs when GitHub returns 403 Forbidden response with a rate limit // remaining value of 0, and error message starts with "API rate limit exceeded for ". type RateLimitError struct { Rate Rate // Rate specifies last known rate limit for the client Response *http.Response // HTTP response that caused this error Message string `json:"message"` // error message } func (r *RateLimitError) Error() string { return fmt.Sprintf("%v %v: %d %v %v", r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), r.Response.StatusCode, r.Message, formatRateReset(time.Until(r.Rate.Reset.Time))) } // AcceptedError occurs when GitHub returns 202 Accepted response with an // empty body, which means a job was scheduled on the GitHub side to process // the information needed and cache it. // Technically, 202 Accepted is not a real error, it's just used to // indicate that results are not ready yet, but should be available soon. // The request can be repeated after some time. type AcceptedError struct { // Raw contains the response body. Raw []byte } func (*AcceptedError) Error() string { return "job scheduled on GitHub side; try again later" } // AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the // "documentation_url" field value equal to "https://developer.github.com/v3/#abuse-rate-limits". type AbuseRateLimitError struct { Response *http.Response // HTTP response that caused this error Message string `json:"message"` // error message // RetryAfter is provided with some abuse rate limit errors. If present, // it is the amount of time that the client should wait before retrying. // Otherwise, the client should try again later (after an unspecified amount of time). RetryAfter *time.Duration } func (r *AbuseRateLimitError) Error() string { return fmt.Sprintf("%v %v: %d %v", r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), r.Response.StatusCode, r.Message) } // sanitizeURL redacts the client_secret parameter from the URL which may be // exposed to the user. func sanitizeURL(uri *url.URL) *url.URL { if uri == nil { return nil } params := uri.Query() if len(params.Get("client_secret")) > 0 { params.Set("client_secret", "REDACTED") uri.RawQuery = params.Encode() } return uri } /* An Error reports more details on an individual error in an ErrorResponse. These are the possible validation error codes: missing: resource does not exist missing_field: a required field on a resource has not been set invalid: the formatting of a field is invalid already_exists: another resource has the same valid as this field custom: some resources return this (e.g. github.User.CreateKey()), additional information is set in the Message field of the Error GitHub API docs: https://developer.github.com/v3/#client-errors */ type Error struct { Resource string `json:"resource"` // resource on which the error occurred Field string `json:"field"` // field on which the error occurred Code string `json:"code"` // validation error code Message string `json:"message"` // Message describing the error. Errors with Code == "custom" will always have this set. } func (e *Error) Error() string { return fmt.Sprintf("%v error caused by %v field on %v resource", e.Code, e.Field, e.Resource) } // CheckResponse checks the API response for errors, and returns them if // present. A response is considered an error if it has a status code outside // the 200 range or equal to 202 Accepted. // API error responses are expected to have either no response // body, or a JSON response body that maps to ErrorResponse. Any other // response body will be silently ignored. // // The error type will be *RateLimitError for rate limit exceeded errors, // *AcceptedError for 202 Accepted status codes, // and *TwoFactorAuthError for two-factor authentication errors. func CheckResponse(r *http.Response) error { if r.StatusCode == http.StatusAccepted { return &AcceptedError{} } if c := r.StatusCode; 200 <= c && c <= 299 { return nil } errorResponse := &ErrorResponse{Response: r} data, err := ioutil.ReadAll(r.Body) if err == nil && data != nil { json.Unmarshal(data, errorResponse) } switch { case r.StatusCode == http.StatusUnauthorized && strings.HasPrefix(r.Header.Get(headerOTP), "required"): return (*TwoFactorAuthError)(errorResponse) case r.StatusCode == http.StatusForbidden && r.Header.Get(headerRateRemaining) == "0" && strings.HasPrefix(errorResponse.Message, "API rate limit exceeded for "): return &RateLimitError{ Rate: parseRate(r), Response: errorResponse.Response, Message: errorResponse.Message, } case r.StatusCode == http.StatusForbidden && strings.HasSuffix(errorResponse.DocumentationURL, "/v3/#abuse-rate-limits"): abuseRateLimitError := &AbuseRateLimitError{ Response: errorResponse.Response, Message: errorResponse.Message, } if v := r.Header["Retry-After"]; len(v) > 0 { // According to GitHub support, the "Retry-After" header value will be // an integer which represents the number of seconds that one should // wait before resuming making requests. retryAfterSeconds, _ := strconv.ParseInt(v[0], 10, 64) // Error handling is noop. retryAfter := time.Duration(retryAfterSeconds) * time.Second abuseRateLimitError.RetryAfter = &retryAfter } return abuseRateLimitError default: return errorResponse } } // parseBoolResponse determines the boolean result from a GitHub API response. // Several GitHub API methods return boolean responses indicated by the HTTP // status code in the response (true indicated by a 204, false indicated by a // 404). This helper function will determine that result and hide the 404 // error if present. Any other error will be returned through as-is. func parseBoolResponse(err error) (bool, error) { if err == nil { return true, nil } if err, ok := err.(*ErrorResponse); ok && err.Response.StatusCode == http.StatusNotFound { // Simply false. In this one case, we do not pass the error through. return false, nil } // some other real error occurred return false, err } // Rate represents the rate limit for the current client. type Rate struct { // The number of requests per hour the client is currently limited to. Limit int `json:"limit"` // The number of remaining requests the client can make this hour. Remaining int `json:"remaining"` // The time at which the current rate limit will reset. Reset Timestamp `json:"reset"` } func (r Rate) String() string { return Stringify(r) } // RateLimits represents the rate limits for the current client. type RateLimits struct { // The rate limit for non-search API requests. Unauthenticated // requests are limited to 60 per hour. Authenticated requests are // limited to 5,000 per hour. // // GitHub API docs: https://developer.github.com/v3/#rate-limiting Core *Rate `json:"core"` // The rate limit for search API requests. Unauthenticated requests // are limited to 10 requests per minutes. Authenticated requests are // limited to 30 per minute. // // GitHub API docs: https://developer.github.com/v3/search/#rate-limit Search *Rate `json:"search"` } func (r RateLimits) String() string { return Stringify(r) } type rateLimitCategory uint8 const ( coreCategory rateLimitCategory = iota searchCategory categories // An array of this length will be able to contain all rate limit categories. ) // category returns the rate limit category of the endpoint, determined by Request.URL.Path. func category(path string) rateLimitCategory { switch { default: return coreCategory case strings.HasPrefix(path, "/search/"): return searchCategory } } // RateLimits returns the rate limits for the current client. func (c *Client) RateLimits(ctx context.Context) (*RateLimits, *Response, error) { req, err := c.NewRequest("GET", "rate_limit", nil) if err != nil { return nil, nil, err } response := new(struct { Resources *RateLimits `json:"resources"` }) resp, err := c.Do(ctx, req, response) if err != nil { return nil, nil, err } if response.Resources != nil { c.rateMu.Lock() if response.Resources.Core != nil { c.rateLimits[coreCategory] = *response.Resources.Core } if response.Resources.Search != nil { c.rateLimits[searchCategory] = *response.Resources.Search } c.rateMu.Unlock() } return response.Resources, resp, nil } /* UnauthenticatedRateLimitedTransport allows you to make unauthenticated calls that need to use a higher rate limit associated with your OAuth application. t := &github.UnauthenticatedRateLimitedTransport{ ClientID: "your app's client ID", ClientSecret: "your app's client secret", } client := github.NewClient(t.Client()) This will append the querystring params client_id=xxx&client_secret=yyy to all requests. See https://developer.github.com/v3/#unauthenticated-rate-limited-requests for more information. */ type UnauthenticatedRateLimitedTransport struct { // ClientID is the GitHub OAuth client ID of the current application, which // can be found by selecting its entry in the list at // https://github.com/settings/applications. ClientID string // ClientSecret is the GitHub OAuth client secret of the current // application. ClientSecret string // Transport is the underlying HTTP transport to use when making requests. // It will default to http.DefaultTransport if nil. Transport http.RoundTripper } // RoundTrip implements the RoundTripper interface. func (t *UnauthenticatedRateLimitedTransport) RoundTrip(req *http.Request) (*http.Response, error) { if t.ClientID == "" { return nil, errors.New("t.ClientID is empty") } if t.ClientSecret == "" { return nil, errors.New("t.ClientSecret is empty") } // To set extra querystring params, we must make a copy of the Request so // that we don't modify the Request we were given. This is required by the // specification of http.RoundTripper. // // Since we are going to modify only req.URL here, we only need a deep copy // of req.URL. req2 := new(http.Request) *req2 = *req req2.URL = new(url.URL) *req2.URL = *req.URL q := req2.URL.Query() q.Set("client_id", t.ClientID) q.Set("client_secret", t.ClientSecret) req2.URL.RawQuery = q.Encode() // Make the HTTP request. return t.transport().RoundTrip(req2) } // Client returns an *http.Client that makes requests which are subject to the // rate limit of your OAuth application. func (t *UnauthenticatedRateLimitedTransport) Client() *http.Client { return &http.Client{Transport: t} } func (t *UnauthenticatedRateLimitedTransport) transport() http.RoundTripper { if t.Transport != nil { return t.Transport } return http.DefaultTransport } // BasicAuthTransport is an http.RoundTripper that authenticates all requests // using HTTP Basic Authentication with the provided username and password. It // additionally supports users who have two-factor authentication enabled on // their GitHub account. type BasicAuthTransport struct { Username string // GitHub username Password string // GitHub password OTP string // one-time password for users with two-factor auth enabled // Transport is the underlying HTTP transport to use when making requests. // It will default to http.DefaultTransport if nil. Transport http.RoundTripper } // RoundTrip implements the RoundTripper interface. func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { // To set extra headers, we must make a copy of the Request so // that we don't modify the Request we were given. This is required by the // specification of http.RoundTripper. // // Since we are going to modify only req.Header here, we only need a deep copy // of req.Header. req2 := new(http.Request) *req2 = *req req2.Header = make(http.Header, len(req.Header)) for k, s := range req.Header { req2.Header[k] = append([]string(nil), s...) } req2.SetBasicAuth(t.Username, t.Password) if t.OTP != "" { req2.Header.Set(headerOTP, t.OTP) } return t.transport().RoundTrip(req2) } // Client returns an *http.Client that makes requests that are authenticated // using HTTP Basic Authentication. func (t *BasicAuthTransport) Client() *http.Client { return &http.Client{Transport: t} } func (t *BasicAuthTransport) transport() http.RoundTripper { if t.Transport != nil { return t.Transport } return http.DefaultTransport } // formatRateReset formats d to look like "[rate reset in 2s]" or // "[rate reset in 87m02s]" for the positive durations. And like "[rate limit was reset 87m02s ago]" // for the negative cases. func formatRateReset(d time.Duration) string { isNegative := d < 0 if isNegative { d *= -1 } secondsTotal := int(0.5 + d.Seconds()) minutes := secondsTotal / 60 seconds := secondsTotal - minutes*60 var timeString string if minutes > 0 { timeString = fmt.Sprintf("%dm%02ds", minutes, seconds) } else { timeString = fmt.Sprintf("%ds", seconds) } if isNegative { return fmt.Sprintf("[rate limit was reset %v ago]", timeString) } return fmt.Sprintf("[rate reset in %v]", timeString) } // Bool is a helper routine that allocates a new bool value // to store v and returns a pointer to it. func Bool(v bool) *bool { return &v } // Int is a helper routine that allocates a new int value // to store v and returns a pointer to it. func Int(v int) *int { return &v } // Int64 is a helper routine that allocates a new int64 value // to store v and returns a pointer to it. func Int64(v int64) *int64 { return &v } // String is a helper routine that allocates a new string value // to store v and returns a pointer to it. func String(v string) *string { return &v } go-github-28.1.1/github/github_test.go000066400000000000000000001031211353501270500176210ustar00rootroot00000000000000// 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 ( "bytes" "context" "encoding/json" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/url" "os" "path" "reflect" "strings" "testing" "time" ) const ( // baseURLPath is a non-empty Client.BaseURL path to use during tests, // to ensure relative URLs are used for all endpoints. See issue #752. baseURLPath = "/api-v3" ) // setup sets up a test HTTP server along with a github.Client that is // configured to talk to that test server. Tests should register handlers on // mux which provide mock responses for the API method being tested. func setup() (client *Client, mux *http.ServeMux, serverURL string, teardown func()) { // mux is the HTTP request multiplexer used with the test server. mux = http.NewServeMux() // We want to ensure that tests catch mistakes where the endpoint URL is // specified as absolute rather than relative. It only makes a difference // when there's a non-empty base URL path. So, use that. See issue #752. apiHandler := http.NewServeMux() apiHandler.Handle(baseURLPath+"/", http.StripPrefix(baseURLPath, mux)) apiHandler.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { fmt.Fprintln(os.Stderr, "FAIL: Client.BaseURL path prefix is not preserved in the request URL:") fmt.Fprintln(os.Stderr) fmt.Fprintln(os.Stderr, "\t"+req.URL.String()) fmt.Fprintln(os.Stderr) fmt.Fprintln(os.Stderr, "\tDid you accidentally use an absolute endpoint URL rather than relative?") fmt.Fprintln(os.Stderr, "\tSee https://github.com/google/go-github/issues/752 for information.") http.Error(w, "Client.BaseURL path prefix is not preserved in the request URL.", http.StatusInternalServerError) }) // server is a test HTTP server used to provide mock API responses. server := httptest.NewServer(apiHandler) // client is the GitHub client being tested and is // configured to use test server. client = NewClient(nil) url, _ := url.Parse(server.URL + baseURLPath + "/") client.BaseURL = url client.UploadURL = url return client, mux, server.URL, server.Close } // openTestFile creates a new file with the given name and content for testing. // In order to ensure the exact file name, this function will create a new temp // directory, and create the file in that directory. It is the caller's // responsibility to remove the directory and its contents when no longer needed. func openTestFile(name, content string) (file *os.File, dir string, err error) { dir, err = ioutil.TempDir("", "go-github") if err != nil { return nil, dir, err } file, err = os.OpenFile(path.Join(dir, name), os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) if err != nil { return nil, dir, err } fmt.Fprint(file, content) // close and re-open the file to keep file.Stat() happy file.Close() file, err = os.Open(file.Name()) if err != nil { return nil, dir, err } return file, dir, err } func testMethod(t *testing.T, r *http.Request, want string) { if got := r.Method; got != want { t.Errorf("Request method: %v, want %v", got, want) } } type values map[string]string func testFormValues(t *testing.T, r *http.Request, values values) { want := url.Values{} for k, v := range values { want.Set(k, v) } r.ParseForm() if got := r.Form; !reflect.DeepEqual(got, want) { t.Errorf("Request parameters: %v, want %v", got, want) } } func testHeader(t *testing.T, r *http.Request, header string, want string) { if got := r.Header.Get(header); got != want { t.Errorf("Header.Get(%q) returned %q, want %q", header, got, want) } } func testURLParseError(t *testing.T, err error) { if err == nil { t.Errorf("Expected error to be returned") } if err, ok := err.(*url.Error); !ok || err.Op != "parse" { t.Errorf("Expected URL parse error, got %+v", err) } } func testBody(t *testing.T, r *http.Request, want string) { b, err := ioutil.ReadAll(r.Body) if err != nil { t.Errorf("Error reading request body: %v", err) } if got := string(b); got != want { t.Errorf("request Body is %s, want %s", got, want) } } // Helper function to test that a value is marshalled to JSON as expected. func testJSONMarshal(t *testing.T, v interface{}, want string) { j, err := json.Marshal(v) if err != nil { t.Errorf("Unable to marshal JSON for %v", v) } w := new(bytes.Buffer) err = json.Compact(w, []byte(want)) if err != nil { t.Errorf("String is not valid json: %s", want) } if w.String() != string(j) { t.Errorf("json.Marshal(%q) returned %s, want %s", v, j, w) } // now go the other direction and make sure things unmarshal as expected u := reflect.ValueOf(v).Interface() if err := json.Unmarshal([]byte(want), u); err != nil { t.Errorf("Unable to unmarshal JSON for %v: %v", want, err) } if !reflect.DeepEqual(v, u) { t.Errorf("json.Unmarshal(%q) returned %s, want %s", want, u, v) } } func TestNewClient(t *testing.T) { c := NewClient(nil) if got, want := c.BaseURL.String(), defaultBaseURL; got != want { t.Errorf("NewClient BaseURL is %v, want %v", got, want) } if got, want := c.UserAgent, userAgent; got != want { t.Errorf("NewClient UserAgent is %v, want %v", got, want) } c2 := NewClient(nil) if c.client == c2.client { t.Error("NewClient returned same http.Clients, but they should differ") } } func TestNewEnterpriseClient(t *testing.T) { baseURL := "https://custom-url/" uploadURL := "https://custom-upload-url/" c, err := NewEnterpriseClient(baseURL, uploadURL, nil) if err != nil { t.Fatalf("NewEnterpriseClient returned unexpected error: %v", err) } if got, want := c.BaseURL.String(), baseURL; got != want { t.Errorf("NewClient BaseURL is %v, want %v", got, want) } if got, want := c.UploadURL.String(), uploadURL; got != want { t.Errorf("NewClient UploadURL is %v, want %v", got, want) } } func TestNewEnterpriseClient_addsTrailingSlashToURLs(t *testing.T) { baseURL := "https://custom-url" uploadURL := "https://custom-upload-url" formattedBaseURL := baseURL + "/" formattedUploadURL := uploadURL + "/" c, err := NewEnterpriseClient(baseURL, uploadURL, nil) if err != nil { t.Fatalf("NewEnterpriseClient returned unexpected error: %v", err) } if got, want := c.BaseURL.String(), formattedBaseURL; got != want { t.Errorf("NewClient BaseURL is %v, want %v", got, want) } if got, want := c.UploadURL.String(), formattedUploadURL; got != want { t.Errorf("NewClient UploadURL is %v, want %v", got, want) } } // Ensure that length of Client.rateLimits is the same as number of fields in RateLimits struct. func TestClient_rateLimits(t *testing.T) { if got, want := len(Client{}.rateLimits), reflect.TypeOf(RateLimits{}).NumField(); got != want { t.Errorf("len(Client{}.rateLimits) is %v, want %v", got, want) } } func TestRateLimits_String(t *testing.T) { v := RateLimits{ Core: &Rate{}, Search: &Rate{}, } want := `github.RateLimits{Core:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, Search:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}}` if got := v.String(); got != want { t.Errorf("RateLimits.String = %v, want %v", got, want) } } func TestNewRequest(t *testing.T) { c := NewClient(nil) inURL, outURL := "/foo", defaultBaseURL+"foo" inBody, outBody := &User{Login: String("l")}, `{"login":"l"}`+"\n" req, _ := c.NewRequest("GET", inURL, inBody) // test that relative URL was expanded if got, want := req.URL.String(), outURL; got != want { t.Errorf("NewRequest(%q) URL is %v, want %v", inURL, got, want) } // test that body was JSON encoded body, _ := ioutil.ReadAll(req.Body) if got, want := string(body), outBody; got != want { t.Errorf("NewRequest(%q) Body is %v, want %v", inBody, got, want) } // test that default user-agent is attached to the request if got, want := req.Header.Get("User-Agent"), c.UserAgent; got != want { t.Errorf("NewRequest() User-Agent is %v, want %v", got, want) } } func TestNewRequest_invalidJSON(t *testing.T) { c := NewClient(nil) type T struct { A map[interface{}]interface{} } _, err := c.NewRequest("GET", ".", &T{}) if err == nil { t.Error("Expected error to be returned.") } if err, ok := err.(*json.UnsupportedTypeError); !ok { t.Errorf("Expected a JSON error; got %#v.", err) } } func TestNewRequest_badURL(t *testing.T) { c := NewClient(nil) _, err := c.NewRequest("GET", ":", nil) testURLParseError(t, err) } // ensure that no User-Agent header is set if the client's UserAgent is empty. // This caused a problem with Google's internal http client. func TestNewRequest_emptyUserAgent(t *testing.T) { c := NewClient(nil) c.UserAgent = "" req, err := c.NewRequest("GET", ".", nil) if err != nil { t.Fatalf("NewRequest returned unexpected error: %v", err) } if _, ok := req.Header["User-Agent"]; ok { t.Fatal("constructed request contains unexpected User-Agent header") } } // If a nil body is passed to github.NewRequest, make sure that nil is also // passed to http.NewRequest. In most cases, passing an io.Reader that returns // no content is fine, since there is no difference between an HTTP request // body that is an empty string versus one that is not set at all. However in // certain cases, intermediate systems may treat these differently resulting in // subtle errors. func TestNewRequest_emptyBody(t *testing.T) { c := NewClient(nil) req, err := c.NewRequest("GET", ".", nil) if err != nil { t.Fatalf("NewRequest returned unexpected error: %v", err) } if req.Body != nil { t.Fatalf("constructed request contains a non-nil Body") } } func TestNewRequest_errorForNoTrailingSlash(t *testing.T) { tests := []struct { rawurl string wantError bool }{ {rawurl: "https://example.com/api/v3", wantError: true}, {rawurl: "https://example.com/api/v3/", wantError: false}, } c := NewClient(nil) for _, test := range tests { u, err := url.Parse(test.rawurl) if err != nil { t.Fatalf("url.Parse returned unexpected error: %v.", err) } c.BaseURL = u if _, err := c.NewRequest(http.MethodGet, "test", nil); test.wantError && err == nil { t.Fatalf("Expected error to be returned.") } else if !test.wantError && err != nil { t.Fatalf("NewRequest returned unexpected error: %v.", err) } } } func TestNewUploadRequest_errorForNoTrailingSlash(t *testing.T) { tests := []struct { rawurl string wantError bool }{ {rawurl: "https://example.com/api/uploads", wantError: true}, {rawurl: "https://example.com/api/uploads/", wantError: false}, } c := NewClient(nil) for _, test := range tests { u, err := url.Parse(test.rawurl) if err != nil { t.Fatalf("url.Parse returned unexpected error: %v.", err) } c.UploadURL = u if _, err = c.NewUploadRequest("test", nil, 0, ""); test.wantError && err == nil { t.Fatalf("Expected error to be returned.") } else if !test.wantError && err != nil { t.Fatalf("NewUploadRequest returned unexpected error: %v.", err) } } } func TestResponse_populatePageValues(t *testing.T) { r := http.Response{ Header: http.Header{ "Link": {`; rel="first",` + ` ; rel="prev",` + ` ; rel="next",` + ` ; rel="last"`, }, }, } response := newResponse(&r) if got, want := response.FirstPage, 1; got != want { t.Errorf("response.FirstPage: %v, want %v", got, want) } if got, want := response.PrevPage, 2; want != got { t.Errorf("response.PrevPage: %v, want %v", got, want) } if got, want := response.NextPage, 4; want != got { t.Errorf("response.NextPage: %v, want %v", got, want) } if got, want := response.LastPage, 5; want != got { t.Errorf("response.LastPage: %v, want %v", got, want) } } func TestResponse_populatePageValues_invalid(t *testing.T) { r := http.Response{ Header: http.Header{ "Link": {`,` + `; rel="first",` + `https://api.github.com/?page=2; rel="prev",` + `; rel="next",` + `; rel="last"`, }, }, } response := newResponse(&r) if got, want := response.FirstPage, 0; got != want { t.Errorf("response.FirstPage: %v, want %v", got, want) } if got, want := response.PrevPage, 0; got != want { t.Errorf("response.PrevPage: %v, want %v", got, want) } if got, want := response.NextPage, 0; got != want { t.Errorf("response.NextPage: %v, want %v", got, want) } if got, want := response.LastPage, 0; got != want { t.Errorf("response.LastPage: %v, want %v", got, want) } // more invalid URLs r = http.Response{ Header: http.Header{ "Link": {`; rel="first"`}, }, } response = newResponse(&r) if got, want := response.FirstPage, 0; got != want { t.Errorf("response.FirstPage: %v, want %v", got, want) } } func TestDo(t *testing.T) { client, mux, _, teardown := setup() defer teardown() type foo struct { A string } mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"A":"a"}`) }) req, _ := client.NewRequest("GET", ".", nil) body := new(foo) client.Do(context.Background(), req, body) want := &foo{"a"} if !reflect.DeepEqual(body, want) { t.Errorf("Response body = %v, want %v", body, want) } } func TestDo_httpError(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Bad Request", 400) }) req, _ := client.NewRequest("GET", ".", nil) resp, err := client.Do(context.Background(), req, nil) if err == nil { t.Fatal("Expected HTTP 400 error, got no error.") } if resp.StatusCode != 400 { t.Errorf("Expected HTTP 400 error, got %d status code.", resp.StatusCode) } } // Test handling of an error caused by the internal http client's Do() // function. A redirect loop is pretty unlikely to occur within the GitHub // API, but does allow us to exercise the right code path. func TestDo_redirectLoop(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, baseURLPath, http.StatusFound) }) req, _ := client.NewRequest("GET", ".", nil) _, err := client.Do(context.Background(), req, nil) if err == nil { t.Error("Expected error to be returned.") } if err, ok := err.(*url.Error); !ok { t.Errorf("Expected a URL error; got %#v.", err) } } // Test that an error caused by the internal http client's Do() function // does not leak the client secret. func TestDo_sanitizeURL(t *testing.T) { tp := &UnauthenticatedRateLimitedTransport{ ClientID: "id", ClientSecret: "secret", } unauthedClient := NewClient(tp.Client()) unauthedClient.BaseURL = &url.URL{Scheme: "http", Host: "127.0.0.1:0", Path: "/"} // Use port 0 on purpose to trigger a dial TCP error, expect to get "dial tcp 127.0.0.1:0: connect: can't assign requested address". req, err := unauthedClient.NewRequest("GET", ".", nil) if err != nil { t.Fatalf("NewRequest returned unexpected error: %v", err) } _, err = unauthedClient.Do(context.Background(), req, nil) if err == nil { t.Fatal("Expected error to be returned.") } if strings.Contains(err.Error(), "client_secret=secret") { t.Errorf("Do error contains secret, should be redacted:\n%q", err) } } func TestDo_rateLimit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set(headerRateLimit, "60") w.Header().Set(headerRateRemaining, "59") w.Header().Set(headerRateReset, "1372700873") }) req, _ := client.NewRequest("GET", ".", nil) resp, err := client.Do(context.Background(), req, nil) if err != nil { t.Errorf("Do returned unexpected error: %v", err) } if got, want := resp.Rate.Limit, 60; got != want { t.Errorf("Client rate limit = %v, want %v", got, want) } if got, want := resp.Rate.Remaining, 59; got != want { t.Errorf("Client rate remaining = %v, want %v", got, want) } reset := time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC) if resp.Rate.Reset.UTC() != reset { t.Errorf("Client rate reset = %v, want %v", resp.Rate.Reset, reset) } } // ensure rate limit is still parsed, even for error responses func TestDo_rateLimit_errorResponse(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set(headerRateLimit, "60") w.Header().Set(headerRateRemaining, "59") w.Header().Set(headerRateReset, "1372700873") http.Error(w, "Bad Request", 400) }) req, _ := client.NewRequest("GET", ".", nil) resp, err := client.Do(context.Background(), req, nil) if err == nil { t.Error("Expected error to be returned.") } if _, ok := err.(*RateLimitError); ok { t.Errorf("Did not expect a *RateLimitError error; got %#v.", err) } if got, want := resp.Rate.Limit, 60; got != want { t.Errorf("Client rate limit = %v, want %v", got, want) } if got, want := resp.Rate.Remaining, 59; got != want { t.Errorf("Client rate remaining = %v, want %v", got, want) } reset := time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC) if resp.Rate.Reset.UTC() != reset { t.Errorf("Client rate reset = %v, want %v", resp.Rate.Reset, reset) } } // Ensure *RateLimitError is returned when API rate limit is exceeded. func TestDo_rateLimit_rateLimitError(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set(headerRateLimit, "60") w.Header().Set(headerRateRemaining, "0") w.Header().Set(headerRateReset, "1372700873") w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(http.StatusForbidden) fmt.Fprintln(w, `{ "message": "API rate limit exceeded for xxx.xxx.xxx.xxx. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)", "documentation_url": "https://developer.github.com/v3/#rate-limiting" }`) }) req, _ := client.NewRequest("GET", ".", nil) _, err := client.Do(context.Background(), req, nil) if err == nil { t.Error("Expected error to be returned.") } rateLimitErr, ok := err.(*RateLimitError) if !ok { t.Fatalf("Expected a *RateLimitError error; got %#v.", err) } if got, want := rateLimitErr.Rate.Limit, 60; got != want { t.Errorf("rateLimitErr rate limit = %v, want %v", got, want) } if got, want := rateLimitErr.Rate.Remaining, 0; got != want { t.Errorf("rateLimitErr rate remaining = %v, want %v", got, want) } reset := time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC) if rateLimitErr.Rate.Reset.UTC() != reset { t.Errorf("rateLimitErr rate reset = %v, want %v", rateLimitErr.Rate.Reset.UTC(), reset) } } // Ensure a network call is not made when it's known that API rate limit is still exceeded. func TestDo_rateLimit_noNetworkCall(t *testing.T) { client, mux, _, teardown := setup() defer teardown() reset := time.Now().UTC().Add(time.Minute).Round(time.Second) // Rate reset is a minute from now, with 1 second precision. mux.HandleFunc("/first", func(w http.ResponseWriter, r *http.Request) { w.Header().Set(headerRateLimit, "60") w.Header().Set(headerRateRemaining, "0") w.Header().Set(headerRateReset, fmt.Sprint(reset.Unix())) w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(http.StatusForbidden) fmt.Fprintln(w, `{ "message": "API rate limit exceeded for xxx.xxx.xxx.xxx. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)", "documentation_url": "https://developer.github.com/v3/#rate-limiting" }`) }) madeNetworkCall := false mux.HandleFunc("/second", func(w http.ResponseWriter, r *http.Request) { madeNetworkCall = true }) // First request is made, and it makes the client aware of rate reset time being in the future. req, _ := client.NewRequest("GET", "first", nil) client.Do(context.Background(), req, nil) // Second request should not cause a network call to be made, since client can predict a rate limit error. req, _ = client.NewRequest("GET", "second", nil) _, err := client.Do(context.Background(), req, nil) if madeNetworkCall { t.Fatal("Network call was made, even though rate limit is known to still be exceeded.") } if err == nil { t.Error("Expected error to be returned.") } rateLimitErr, ok := err.(*RateLimitError) if !ok { t.Fatalf("Expected a *RateLimitError error; got %#v.", err) } if got, want := rateLimitErr.Rate.Limit, 60; got != want { t.Errorf("rateLimitErr rate limit = %v, want %v", got, want) } if got, want := rateLimitErr.Rate.Remaining, 0; got != want { t.Errorf("rateLimitErr rate remaining = %v, want %v", got, want) } if rateLimitErr.Rate.Reset.UTC() != reset { t.Errorf("rateLimitErr rate reset = %v, want %v", rateLimitErr.Rate.Reset.UTC(), reset) } } // Ensure *AbuseRateLimitError is returned when the response indicates that // the client has triggered an abuse detection mechanism. func TestDo_rateLimit_abuseRateLimitError(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(http.StatusForbidden) // When the abuse rate limit error is of the "temporarily blocked from content creation" type, // there is no "Retry-After" header. fmt.Fprintln(w, `{ "message": "You have triggered an abuse detection mechanism and have been temporarily blocked from content creation. Please retry your request again later.", "documentation_url": "https://developer.github.com/v3/#abuse-rate-limits" }`) }) req, _ := client.NewRequest("GET", ".", nil) _, err := client.Do(context.Background(), req, nil) if err == nil { t.Error("Expected error to be returned.") } abuseRateLimitErr, ok := err.(*AbuseRateLimitError) if !ok { t.Fatalf("Expected a *AbuseRateLimitError error; got %#v.", err) } if got, want := abuseRateLimitErr.RetryAfter, (*time.Duration)(nil); got != want { t.Errorf("abuseRateLimitErr RetryAfter = %v, want %v", got, want) } } // Ensure *AbuseRateLimitError is returned when the response indicates that // the client has triggered an abuse detection mechanism on GitHub Enterprise. func TestDo_rateLimit_abuseRateLimitErrorEnterprise(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(http.StatusForbidden) // When the abuse rate limit error is of the "temporarily blocked from content creation" type, // there is no "Retry-After" header. // This response returns a documentation url like the one returned for GitHub Enterprise, this // url changes between versions but follows roughly the same format. fmt.Fprintln(w, `{ "message": "You have triggered an abuse detection mechanism and have been temporarily blocked from content creation. Please retry your request again later.", "documentation_url": "https://developer.github.com/enterprise/2.12/v3/#abuse-rate-limits" }`) }) req, _ := client.NewRequest("GET", ".", nil) _, err := client.Do(context.Background(), req, nil) if err == nil { t.Error("Expected error to be returned.") } abuseRateLimitErr, ok := err.(*AbuseRateLimitError) if !ok { t.Fatalf("Expected a *AbuseRateLimitError error; got %#v.", err) } if got, want := abuseRateLimitErr.RetryAfter, (*time.Duration)(nil); got != want { t.Errorf("abuseRateLimitErr RetryAfter = %v, want %v", got, want) } } // Ensure *AbuseRateLimitError.RetryAfter is parsed correctly. func TestDo_rateLimit_abuseRateLimitError_retryAfter(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Retry-After", "123") // Retry after value of 123 seconds. w.WriteHeader(http.StatusForbidden) fmt.Fprintln(w, `{ "message": "You have triggered an abuse detection mechanism ...", "documentation_url": "https://developer.github.com/v3/#abuse-rate-limits" }`) }) req, _ := client.NewRequest("GET", ".", nil) _, err := client.Do(context.Background(), req, nil) if err == nil { t.Error("Expected error to be returned.") } abuseRateLimitErr, ok := err.(*AbuseRateLimitError) if !ok { t.Fatalf("Expected a *AbuseRateLimitError error; got %#v.", err) } if abuseRateLimitErr.RetryAfter == nil { t.Fatalf("abuseRateLimitErr RetryAfter is nil, expected not-nil") } if got, want := *abuseRateLimitErr.RetryAfter, 123*time.Second; got != want { t.Errorf("abuseRateLimitErr RetryAfter = %v, want %v", got, want) } } func TestDo_noContent(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) }) var body json.RawMessage req, _ := client.NewRequest("GET", ".", nil) _, err := client.Do(context.Background(), req, &body) if err != nil { t.Fatalf("Do returned unexpected error: %v", err) } } func TestSanitizeURL(t *testing.T) { tests := []struct { in, want string }{ {"/?a=b", "/?a=b"}, {"/?a=b&client_secret=secret", "/?a=b&client_secret=REDACTED"}, {"/?a=b&client_id=id&client_secret=secret", "/?a=b&client_id=id&client_secret=REDACTED"}, } for _, tt := range tests { inURL, _ := url.Parse(tt.in) want, _ := url.Parse(tt.want) if got := sanitizeURL(inURL); !reflect.DeepEqual(got, want) { t.Errorf("sanitizeURL(%v) returned %v, want %v", tt.in, got, want) } } } func TestCheckResponse(t *testing.T) { res := &http.Response{ Request: &http.Request{}, StatusCode: http.StatusBadRequest, Body: ioutil.NopCloser(strings.NewReader(`{"message":"m", "errors": [{"resource": "r", "field": "f", "code": "c"}], "block": {"reason": "dmca", "created_at": "2016-03-17T15:39:46Z"}}`)), } err := CheckResponse(res).(*ErrorResponse) if err == nil { t.Errorf("Expected error response.") } want := &ErrorResponse{ Response: res, Message: "m", Errors: []Error{{Resource: "r", Field: "f", Code: "c"}}, Block: &struct { Reason string `json:"reason,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` }{ Reason: "dmca", CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, } if !reflect.DeepEqual(err, want) { t.Errorf("Error = %#v, want %#v", err, want) } } // ensure that we properly handle API errors that do not contain a response body func TestCheckResponse_noBody(t *testing.T) { res := &http.Response{ Request: &http.Request{}, StatusCode: http.StatusBadRequest, Body: ioutil.NopCloser(strings.NewReader("")), } err := CheckResponse(res).(*ErrorResponse) if err == nil { t.Errorf("Expected error response.") } want := &ErrorResponse{ Response: res, } if !reflect.DeepEqual(err, want) { t.Errorf("Error = %#v, want %#v", err, want) } } func TestParseBooleanResponse_true(t *testing.T) { result, err := parseBoolResponse(nil) if err != nil { t.Errorf("parseBoolResponse returned error: %+v", err) } if want := true; result != want { t.Errorf("parseBoolResponse returned %+v, want: %+v", result, want) } } func TestParseBooleanResponse_false(t *testing.T) { v := &ErrorResponse{Response: &http.Response{StatusCode: http.StatusNotFound}} result, err := parseBoolResponse(v) if err != nil { t.Errorf("parseBoolResponse returned error: %+v", err) } if want := false; result != want { t.Errorf("parseBoolResponse returned %+v, want: %+v", result, want) } } func TestParseBooleanResponse_error(t *testing.T) { v := &ErrorResponse{Response: &http.Response{StatusCode: http.StatusBadRequest}} result, err := parseBoolResponse(v) if err == nil { t.Errorf("Expected error to be returned.") } if want := false; result != want { t.Errorf("parseBoolResponse returned %+v, want: %+v", result, want) } } func TestErrorResponse_Error(t *testing.T) { res := &http.Response{Request: &http.Request{}} err := ErrorResponse{Message: "m", Response: res} if err.Error() == "" { t.Errorf("Expected non-empty ErrorResponse.Error()") } } func TestError_Error(t *testing.T) { err := Error{} if err.Error() == "" { t.Errorf("Expected non-empty Error.Error()") } } func TestRateLimits(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/rate_limit", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"resources":{ "core": {"limit":2,"remaining":1,"reset":1372700873}, "search": {"limit":3,"remaining":2,"reset":1372700874} }}`) }) rate, _, err := client.RateLimits(context.Background()) if err != nil { t.Errorf("RateLimits returned error: %v", err) } want := &RateLimits{ Core: &Rate{ Limit: 2, Remaining: 1, Reset: Timestamp{time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC).Local()}, }, Search: &Rate{ Limit: 3, Remaining: 2, Reset: Timestamp{time.Date(2013, time.July, 1, 17, 47, 54, 0, time.UTC).Local()}, }, } if !reflect.DeepEqual(rate, want) { t.Errorf("RateLimits returned %+v, want %+v", rate, want) } if got, want := client.rateLimits[coreCategory], *want.Core; got != want { t.Errorf("client.rateLimits[coreCategory] is %+v, want %+v", got, want) } if got, want := client.rateLimits[searchCategory], *want.Search; got != want { t.Errorf("client.rateLimits[searchCategory] is %+v, want %+v", got, want) } } func TestUnauthenticatedRateLimitedTransport(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { var v, want string q := r.URL.Query() if v, want = q.Get("client_id"), "id"; v != want { t.Errorf("OAuth Client ID = %v, want %v", v, want) } if v, want = q.Get("client_secret"), "secret"; v != want { t.Errorf("OAuth Client Secret = %v, want %v", v, want) } }) tp := &UnauthenticatedRateLimitedTransport{ ClientID: "id", ClientSecret: "secret", } unauthedClient := NewClient(tp.Client()) unauthedClient.BaseURL = client.BaseURL req, _ := unauthedClient.NewRequest("GET", ".", nil) unauthedClient.Do(context.Background(), req, nil) } func TestUnauthenticatedRateLimitedTransport_missingFields(t *testing.T) { // missing ClientID tp := &UnauthenticatedRateLimitedTransport{ ClientSecret: "secret", } _, err := tp.RoundTrip(nil) if err == nil { t.Errorf("Expected error to be returned") } // missing ClientSecret tp = &UnauthenticatedRateLimitedTransport{ ClientID: "id", } _, err = tp.RoundTrip(nil) if err == nil { t.Errorf("Expected error to be returned") } } func TestUnauthenticatedRateLimitedTransport_transport(t *testing.T) { // default transport tp := &UnauthenticatedRateLimitedTransport{ ClientID: "id", ClientSecret: "secret", } if tp.transport() != http.DefaultTransport { t.Errorf("Expected http.DefaultTransport to be used.") } // custom transport tp = &UnauthenticatedRateLimitedTransport{ ClientID: "id", ClientSecret: "secret", Transport: &http.Transport{}, } if tp.transport() == http.DefaultTransport { t.Errorf("Expected custom transport to be used.") } } func TestBasicAuthTransport(t *testing.T) { client, mux, _, teardown := setup() defer teardown() username, password, otp := "u", "p", "123456" mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { u, p, ok := r.BasicAuth() if !ok { t.Errorf("request does not contain basic auth credentials") } if u != username { t.Errorf("request contained basic auth username %q, want %q", u, username) } if p != password { t.Errorf("request contained basic auth password %q, want %q", p, password) } if got, want := r.Header.Get(headerOTP), otp; got != want { t.Errorf("request contained OTP %q, want %q", got, want) } }) tp := &BasicAuthTransport{ Username: username, Password: password, OTP: otp, } basicAuthClient := NewClient(tp.Client()) basicAuthClient.BaseURL = client.BaseURL req, _ := basicAuthClient.NewRequest("GET", ".", nil) basicAuthClient.Do(context.Background(), req, nil) } func TestBasicAuthTransport_transport(t *testing.T) { // default transport tp := &BasicAuthTransport{} if tp.transport() != http.DefaultTransport { t.Errorf("Expected http.DefaultTransport to be used.") } // custom transport tp = &BasicAuthTransport{ Transport: &http.Transport{}, } if tp.transport() == http.DefaultTransport { t.Errorf("Expected custom transport to be used.") } } func TestFormatRateReset(t *testing.T) { d := 120*time.Minute + 12*time.Second got := formatRateReset(d) want := "[rate reset in 120m12s]" if got != want { t.Errorf("Format is wrong. got: %v, want: %v", got, want) } d = 14*time.Minute + 2*time.Second got = formatRateReset(d) want = "[rate reset in 14m02s]" if got != want { t.Errorf("Format is wrong. got: %v, want: %v", got, want) } d = 2*time.Minute + 2*time.Second got = formatRateReset(d) want = "[rate reset in 2m02s]" if got != want { t.Errorf("Format is wrong. got: %v, want: %v", got, want) } d = 12 * time.Second got = formatRateReset(d) want = "[rate reset in 12s]" if got != want { t.Errorf("Format is wrong. got: %v, want: %v", got, want) } d = -1 * (2*time.Hour + 2*time.Second) got = formatRateReset(d) want = "[rate limit was reset 120m02s ago]" if got != want { t.Errorf("Format is wrong. got: %v, want: %v", got, want) } } func TestNestedStructAccessorNoPanic(t *testing.T) { issue := &Issue{User: nil} got := issue.GetUser().GetPlan().GetName() want := "" if got != want { t.Errorf("Issues.Get.GetUser().GetPlan().GetName() returned %+v, want %+v", got, want) } } go-github-28.1.1/github/gitignore.go000066400000000000000000000032041353501270500172700ustar00rootroot00000000000000// 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" ) // GitignoresService provides access to the gitignore related functions in the // GitHub API. // // GitHub API docs: https://developer.github.com/v3/gitignore/ type GitignoresService service // Gitignore represents a .gitignore file as returned by the GitHub API. type Gitignore struct { Name *string `json:"name,omitempty"` Source *string `json:"source,omitempty"` } func (g Gitignore) String() string { return Stringify(g) } // 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) { req, err := s.client.NewRequest("GET", "gitignore/templates", nil) if err != nil { return nil, nil, err } var availableTemplates []string resp, err := s.client.Do(ctx, req, &availableTemplates) if err != nil { return nil, resp, err } return availableTemplates, resp, nil } // 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) { u := fmt.Sprintf("gitignore/templates/%v", name) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } gitignore := new(Gitignore) resp, err := s.client.Do(ctx, req, gitignore) if err != nil { return nil, resp, err } return gitignore, resp, nil } go-github-28.1.1/github/gitignore_test.go000066400000000000000000000031401353501270500203260ustar00rootroot00000000000000// 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" "net/http" "reflect" "testing" ) func TestGitignoresService_List(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gitignore/templates", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `["C", "Go"]`) }) available, _, err := client.Gitignores.List(context.Background()) if err != nil { t.Errorf("Gitignores.List returned error: %v", err) } want := []string{"C", "Go"} if !reflect.DeepEqual(available, want) { t.Errorf("Gitignores.List returned %+v, want %+v", available, want) } } func TestGitignoresService_Get(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/gitignore/templates/name", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"name":"Name","source":"template source"}`) }) gitignore, _, err := client.Gitignores.Get(context.Background(), "name") if err != nil { t.Errorf("Gitignores.List returned error: %v", err) } want := &Gitignore{Name: String("Name"), Source: String("template source")} if !reflect.DeepEqual(gitignore, want) { t.Errorf("Gitignores.Get returned %+v, want %+v", gitignore, want) } } func TestGitignoresService_Get_invalidTemplate(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Gitignores.Get(context.Background(), "%") testURLParseError(t, err) } go-github-28.1.1/github/interactions.go000066400000000000000000000022321353501270500200030ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github // InteractionsService handles communication with the repository and organization related // methods of the GitHub API. // // GitHub API docs: https://developer.github.com/v3/interactions/ type InteractionsService service // InteractionRestriction represents the interaction restrictions for repository and organization. type InteractionRestriction struct { // Specifies the group of GitHub users who can // comment, open issues, or create pull requests for the given repository. // Possible values are: "existing_users", "contributors_only" and "collaborators_only". Limit *string `json:"limit,omitempty"` // Origin specifies the type of the resource to interact with. // Possible values are: "repository" and "organization". Origin *string `json:"origin,omitempty"` // ExpiresAt specifies the time after which the interaction restrictions expire. // The default expiry time is 24 hours from the time restriction is created. ExpiresAt *Timestamp `json:"expires_at,omitempty"` } go-github-28.1.1/github/interactions_orgs.go000066400000000000000000000055411353501270500210430ustar00rootroot00000000000000// Copyright 2019 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" ) // GetRestrictionsForOrg fetches the interaction restrictions for an organization. // // GitHub API docs: https://developer.github.com/v3/interactions/orgs/#get-interaction-restrictions-for-an-organization func (s *InteractionsService) GetRestrictionsForOrg(ctx context.Context, organization string) (*InteractionRestriction, *Response, error) { u := fmt.Sprintf("orgs/%v/interaction-limits", organization) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) organizationInteractions := new(InteractionRestriction) resp, err := s.client.Do(ctx, req, organizationInteractions) if err != nil { return nil, resp, err } return organizationInteractions, resp, nil } // UpdateRestrictionsForOrg adds or updates the interaction restrictions for an organization. // // limit specifies the group of GitHub users who can comment, open issues, or create pull requests // in public repositories for the given organization. // Possible values are: "existing_users", "contributors_only", "collaborators_only". // // GitHub API docs: https://developer.github.com/v3/interactions/orgs/#add-or-update-interaction-restrictions-for-an-organization func (s *InteractionsService) UpdateRestrictionsForOrg(ctx context.Context, organization, limit string) (*InteractionRestriction, *Response, error) { u := fmt.Sprintf("orgs/%v/interaction-limits", organization) interaction := &InteractionRestriction{Limit: String(limit)} req, err := s.client.NewRequest("PUT", u, interaction) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) organizationInteractions := new(InteractionRestriction) resp, err := s.client.Do(ctx, req, organizationInteractions) if err != nil { return nil, resp, err } return organizationInteractions, resp, nil } // RemoveRestrictionsFromOrg removes the interaction restrictions for an organization. // // GitHub API docs: https://developer.github.com/v3/interactions/orgs/#remove-interaction-restrictions-for-an-organization func (s *InteractionsService) RemoveRestrictionsFromOrg(ctx context.Context, organization string) (*Response, error) { u := fmt.Sprintf("orgs/%v/interaction-limits", organization) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/interactions_orgs_test.go000066400000000000000000000051031353501270500220740ustar00rootroot00000000000000// Copyright 2019 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestInteractionsService_GetRestrictionsForOrgs(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/interaction-limits", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeInteractionRestrictionsPreview) fmt.Fprint(w, `{"origin":"organization"}`) }) organizationInteractions, _, err := client.Interactions.GetRestrictionsForOrg(context.Background(), "o") if err != nil { t.Errorf("Interactions.GetRestrictionsForOrg returned error: %v", err) } want := &InteractionRestriction{Origin: String("organization")} if !reflect.DeepEqual(organizationInteractions, want) { t.Errorf("Interactions.GetRestrictionsForOrg returned %+v, want %+v", organizationInteractions, want) } } func TestInteractionsService_UpdateRestrictionsForOrg(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &InteractionRestriction{Limit: String("existing_users")} mux.HandleFunc("/orgs/o/interaction-limits", func(w http.ResponseWriter, r *http.Request) { v := new(InteractionRestriction) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeInteractionRestrictionsPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"origin":"organization"}`) }) organizationInteractions, _, err := client.Interactions.UpdateRestrictionsForOrg(context.Background(), "o", input.GetLimit()) if err != nil { t.Errorf("Interactions.UpdateRestrictionsForOrg returned error: %v", err) } want := &InteractionRestriction{Origin: String("organization")} if !reflect.DeepEqual(organizationInteractions, want) { t.Errorf("Interactions.UpdateRestrictionsForOrg returned %+v, want %+v", organizationInteractions, want) } } func TestInteractionsService_RemoveRestrictionsFromOrg(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/interaction-limits", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeInteractionRestrictionsPreview) }) _, err := client.Interactions.RemoveRestrictionsFromOrg(context.Background(), "o") if err != nil { t.Errorf("Interactions.RemoveRestrictionsFromOrg returned error: %v", err) } } go-github-28.1.1/github/interactions_repos.go000066400000000000000000000054711353501270500212230ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" ) // GetRestrictionsForRepo fetches the interaction restrictions for a repository. // // GitHub API docs: https://developer.github.com/v3/interactions/repos/#get-interaction-restrictions-for-a-repository func (s *InteractionsService) GetRestrictionsForRepo(ctx context.Context, owner, repo string) (*InteractionRestriction, *Response, error) { u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) repositoryInteractions := new(InteractionRestriction) resp, err := s.client.Do(ctx, req, repositoryInteractions) if err != nil { return nil, resp, err } return repositoryInteractions, resp, nil } // UpdateRestrictionsForRepo adds or updates the interaction restrictions for a repository. // // limit specifies the group of GitHub users who can comment, open issues, or create pull requests // for the given repository. // Possible values are: "existing_users", "contributors_only", "collaborators_only". // // GitHub API docs: https://developer.github.com/v3/interactions/repos/#add-or-update-interaction-restrictions-for-a-repository func (s *InteractionsService) UpdateRestrictionsForRepo(ctx context.Context, owner, repo, limit string) (*InteractionRestriction, *Response, error) { u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) interaction := &InteractionRestriction{Limit: String(limit)} req, err := s.client.NewRequest("PUT", u, interaction) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) repositoryInteractions := new(InteractionRestriction) resp, err := s.client.Do(ctx, req, repositoryInteractions) if err != nil { return nil, resp, err } return repositoryInteractions, resp, nil } // RemoveRestrictionsFromRepo removes the interaction restrictions for a repository. // // GitHub API docs: https://developer.github.com/v3/interactions/repos/#remove-interaction-restrictions-for-a-repository func (s *InteractionsService) RemoveRestrictionsFromRepo(ctx context.Context, owner, repo string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/interactions_repos_test.go000066400000000000000000000050551353501270500222600ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestInteractionsService_GetRestrictionsForRepo(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/interaction-limits", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeInteractionRestrictionsPreview) fmt.Fprint(w, `{"origin":"repository"}`) }) repoInteractions, _, err := client.Interactions.GetRestrictionsForRepo(context.Background(), "o", "r") if err != nil { t.Errorf("Interactions.GetRestrictionsForRepo returned error: %v", err) } want := &InteractionRestriction{Origin: String("repository")} if !reflect.DeepEqual(repoInteractions, want) { t.Errorf("Interactions.GetRestrictionsForRepo returned %+v, want %+v", repoInteractions, want) } } func TestInteractionsService_UpdateRestrictionsForRepo(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &InteractionRestriction{Limit: String("existing_users")} mux.HandleFunc("/repos/o/r/interaction-limits", func(w http.ResponseWriter, r *http.Request) { v := new(InteractionRestriction) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeInteractionRestrictionsPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"origin":"repository"}`) }) repoInteractions, _, err := client.Interactions.UpdateRestrictionsForRepo(context.Background(), "o", "r", input.GetLimit()) if err != nil { t.Errorf("Interactions.UpdateRestrictionsForRepo returned error: %v", err) } want := &InteractionRestriction{Origin: String("repository")} if !reflect.DeepEqual(repoInteractions, want) { t.Errorf("Interactions.UpdateRestrictionsForRepo returned %+v, want %+v", repoInteractions, want) } } func TestInteractionsService_RemoveRestrictionsFromRepo(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/interaction-limits", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeInteractionRestrictionsPreview) }) _, err := client.Interactions.RemoveRestrictionsFromRepo(context.Background(), "o", "r") if err != nil { t.Errorf("Interactions.RemoveRestrictionsFromRepo returned error: %v", err) } } go-github-28.1.1/github/issues.go000066400000000000000000000303671353501270500166260ustar00rootroot00000000000000// 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" "strings" "time" ) // IssuesService handles communication with the issue related // methods of the GitHub API. // // GitHub API docs: https://developer.github.com/v3/issues/ type IssuesService service // Issue represents a GitHub issue on a repository. // // Note: As far as the GitHub API is concerned, every pull request is an issue, // but not every issue is a pull request. Some endpoints, events, and webhooks // may also return pull requests via this struct. If PullRequestLinks is nil, // this is an issue, and if PullRequestLinks is not nil, this is a pull request. // The IsPullRequest helper method can be used to check that. type Issue struct { ID *int64 `json:"id,omitempty"` Number *int `json:"number,omitempty"` State *string `json:"state,omitempty"` Locked *bool `json:"locked,omitempty"` Title *string `json:"title,omitempty"` Body *string `json:"body,omitempty"` User *User `json:"user,omitempty"` Labels []Label `json:"labels,omitempty"` Assignee *User `json:"assignee,omitempty"` Comments *int `json:"comments,omitempty"` ClosedAt *time.Time `json:"closed_at,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` ClosedBy *User `json:"closed_by,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` CommentsURL *string `json:"comments_url,omitempty"` EventsURL *string `json:"events_url,omitempty"` LabelsURL *string `json:"labels_url,omitempty"` RepositoryURL *string `json:"repository_url,omitempty"` Milestone *Milestone `json:"milestone,omitempty"` PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"` Repository *Repository `json:"repository,omitempty"` Reactions *Reactions `json:"reactions,omitempty"` Assignees []*User `json:"assignees,omitempty"` NodeID *string `json:"node_id,omitempty"` // TextMatches is only populated from search results that request text matches // See: search.go and https://developer.github.com/v3/search/#text-match-metadata TextMatches []TextMatch `json:"text_matches,omitempty"` // ActiveLockReason is populated only when LockReason is provided while locking the issue. // Possible values are: "off-topic", "too heated", "resolved", and "spam". ActiveLockReason *string `json:"active_lock_reason,omitempty"` } func (i Issue) String() string { return Stringify(i) } // IsPullRequest reports whether the issue is also a pull request. It uses the // method recommended by GitHub's API documentation, which is to check whether // PullRequestLinks is non-nil. func (i Issue) IsPullRequest() bool { return i.PullRequestLinks != nil } // IssueRequest represents a request to create/edit an issue. // It is separate from Issue above because otherwise Labels // and Assignee fail to serialize to the correct JSON. type IssueRequest struct { Title *string `json:"title,omitempty"` Body *string `json:"body,omitempty"` Labels *[]string `json:"labels,omitempty"` Assignee *string `json:"assignee,omitempty"` State *string `json:"state,omitempty"` Milestone *int `json:"milestone,omitempty"` Assignees *[]string `json:"assignees,omitempty"` } // IssueListOptions specifies the optional parameters to the IssuesService.List // and IssuesService.ListByOrg methods. type IssueListOptions struct { // Filter specifies which issues to list. Possible values are: assigned, // created, mentioned, subscribed, all. Default is "assigned". Filter string `url:"filter,omitempty"` // State filters issues based on their state. Possible values are: open, // closed, all. Default is "open". State string `url:"state,omitempty"` // Labels filters issues based on their label. Labels []string `url:"labels,comma,omitempty"` // Sort specifies how to sort issues. Possible values are: created, updated, // and comments. Default value is "created". Sort string `url:"sort,omitempty"` // Direction in which to sort issues. Possible values are: asc, desc. // Default is "desc". Direction string `url:"direction,omitempty"` // Since filters issues by time. Since time.Time `url:"since,omitempty"` ListOptions } // PullRequestLinks object is added to the Issue object when it's an issue included // in the IssueCommentEvent webhook payload, if the webhook is fired by a comment on a PR. type PullRequestLinks struct { URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` DiffURL *string `json:"diff_url,omitempty"` PatchURL *string `json:"patch_url,omitempty"` } // List the issues for the authenticated user. If all is true, list issues // across all the user's visible repositories including owned, member, and // organization repositories; if false, list only owned and member // repositories. // // GitHub API docs: https://developer.github.com/v3/issues/#list-issues func (s *IssuesService) List(ctx context.Context, all bool, opt *IssueListOptions) ([]*Issue, *Response, error) { var u string if all { u = "issues" } else { u = "user/issues" } return s.listIssues(ctx, u, opt) } // ListByOrg fetches the issues in the specified organization for the // authenticated user. // // GitHub API docs: https://developer.github.com/v3/issues/#list-issues func (s *IssuesService) ListByOrg(ctx context.Context, org string, opt *IssueListOptions) ([]*Issue, *Response, error) { u := fmt.Sprintf("orgs/%v/issues", org) return s.listIssues(ctx, u, opt) } func (s *IssuesService) listIssues(ctx context.Context, u string, opt *IssueListOptions) ([]*Issue, *Response, error) { u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var issues []*Issue resp, err := s.client.Do(ctx, req, &issues) if err != nil { return nil, resp, err } return issues, resp, nil } // IssueListByRepoOptions specifies the optional parameters to the // IssuesService.ListByRepo method. type IssueListByRepoOptions struct { // Milestone limits issues for the specified milestone. Possible values are // a milestone number, "none" for issues with no milestone, "*" for issues // with any milestone. Milestone string `url:"milestone,omitempty"` // State filters issues based on their state. Possible values are: open, // closed, all. Default is "open". State string `url:"state,omitempty"` // Assignee filters issues based on their assignee. Possible values are a // user name, "none" for issues that are not assigned, "*" for issues with // any assigned user. Assignee string `url:"assignee,omitempty"` // Creator filters issues based on their creator. Creator string `url:"creator,omitempty"` // Mentioned filters issues to those mentioned a specific user. Mentioned string `url:"mentioned,omitempty"` // Labels filters issues based on their label. Labels []string `url:"labels,omitempty,comma"` // Sort specifies how to sort issues. Possible values are: created, updated, // and comments. Default value is "created". Sort string `url:"sort,omitempty"` // Direction in which to sort issues. Possible values are: asc, desc. // Default is "desc". Direction string `url:"direction,omitempty"` // Since filters issues by time. Since time.Time `url:"since,omitempty"` ListOptions } // ListByRepo lists the issues for the specified repository. // // GitHub API docs: https://developer.github.com/v3/issues/#list-issues-for-a-repository func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo string, opt *IssueListByRepoOptions) ([]*Issue, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeIntegrationPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var issues []*Issue resp, err := s.client.Do(ctx, req, &issues) if err != nil { return nil, resp, err } return issues, resp, nil } // Get a single issue. // // GitHub API docs: https://developer.github.com/v3/issues/#get-a-single-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) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) issue := new(Issue) resp, err := s.client.Do(ctx, req, issue) if err != nil { return nil, resp, err } return issue, resp, nil } // Create a new issue on the specified repository. // // GitHub API docs: https://developer.github.com/v3/issues/#create-an-issue func (s *IssuesService) Create(ctx context.Context, owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) req, err := s.client.NewRequest("POST", u, issue) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) i := new(Issue) resp, err := s.client.Do(ctx, req, i) if err != nil { return nil, resp, err } return i, resp, nil } // Edit an issue. // // GitHub API docs: https://developer.github.com/v3/issues/#edit-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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) i := new(Issue) resp, err := s.client.Do(ctx, req, i) if err != nil { return nil, resp, err } return i, resp, nil } // LockIssueOptions specifies the optional parameters to the // IssuesService.Lock method. type LockIssueOptions struct { // LockReason specifies the reason to lock this issue. // Providing a lock reason can help make it clearer to contributors why an issue // was locked. Possible values are: "off-topic", "too heated", "resolved", and "spam". LockReason string `json:"lock_reason,omitempty"` } // Lock an issue's conversation. // // GitHub API docs: https://developer.github.com/v3/issues/#lock-an-issue func (s *IssuesService) Lock(ctx context.Context, owner string, repo string, number int, opt *LockIssueOptions) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, err } if opt != nil { req.Header.Set("Accept", mediaTypeLockReasonPreview) } return s.client.Do(ctx, req, nil) } // Unlock an issue's conversation. // // GitHub API docs: https://developer.github.com/v3/issues/#unlock-an-issue func (s *IssuesService) Unlock(ctx context.Context, owner string, repo string, number int) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/issues_assignees.go000066400000000000000000000053651353501270500206670ustar00rootroot00000000000000// 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" ) // ListAssignees fetches all available assignees (owners and collaborators) to // which issues may be assigned. // // GitHub API docs: https://developer.github.com/v3/issues/assignees/#list-assignees func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) { u := fmt.Sprintf("repos/%v/%v/assignees", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var assignees []*User resp, err := s.client.Do(ctx, req, &assignees) if err != nil { return nil, resp, err } return assignees, resp, nil } // IsAssignee checks if a user is an assignee for the specified repository. // // GitHub API docs: https://developer.github.com/v3/issues/assignees/#check-assignee func (s *IssuesService) IsAssignee(ctx context.Context, owner, repo, user string) (bool, *Response, error) { u := fmt.Sprintf("repos/%v/%v/assignees/%v", owner, repo, user) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } resp, err := s.client.Do(ctx, req, nil) assignee, err := parseBoolResponse(err) return assignee, resp, err } // AddAssignees adds the provided GitHub users as assignees to the issue. // // GitHub API docs: https://developer.github.com/v3/issues/assignees/#add-assignees-to-an-issue func (s *IssuesService) AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) { users := &struct { Assignees []string `json:"assignees,omitempty"` }{Assignees: assignees} u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number) req, err := s.client.NewRequest("POST", u, users) if err != nil { return nil, nil, err } issue := &Issue{} resp, err := s.client.Do(ctx, req, issue) return issue, resp, err } // RemoveAssignees removes the provided GitHub users as assignees from the issue. // // GitHub API docs: https://developer.github.com/v3/issues/assignees/#remove-assignees-from-an-issue func (s *IssuesService) RemoveAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) { users := &struct { Assignees []string `json:"assignees,omitempty"` }{Assignees: assignees} u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number) req, err := s.client.NewRequest("DELETE", u, users) if err != nil { return nil, nil, err } issue := &Issue{} resp, err := s.client.Do(ctx, req, issue) return issue, resp, err } go-github-28.1.1/github/issues_assignees_test.go000066400000000000000000000114041353501270500217150ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestIssuesService_ListAssignees(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/assignees", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} assignees, _, err := client.Issues.ListAssignees(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Issues.ListAssignees returned error: %v", err) } want := []*User{{ID: Int64(1)}} if !reflect.DeepEqual(assignees, want) { t.Errorf("Issues.ListAssignees returned %+v, want %+v", assignees, want) } } func TestIssuesService_ListAssignees_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.ListAssignees(context.Background(), "%", "r", nil) testURLParseError(t, err) } func TestIssuesService_IsAssignee_true(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/assignees/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") }) assignee, _, err := client.Issues.IsAssignee(context.Background(), "o", "r", "u") if err != nil { t.Errorf("Issues.IsAssignee returned error: %v", err) } if want := true; assignee != want { t.Errorf("Issues.IsAssignee returned %+v, want %+v", assignee, want) } } func TestIssuesService_IsAssignee_false(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/assignees/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) assignee, _, err := client.Issues.IsAssignee(context.Background(), "o", "r", "u") if err != nil { t.Errorf("Issues.IsAssignee returned error: %v", err) } if want := false; assignee != want { t.Errorf("Issues.IsAssignee returned %+v, want %+v", assignee, want) } } func TestIssuesService_IsAssignee_error(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/assignees/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") http.Error(w, "BadRequest", http.StatusBadRequest) }) assignee, _, err := client.Issues.IsAssignee(context.Background(), "o", "r", "u") if err == nil { t.Errorf("Expected HTTP 400 response") } if want := false; assignee != want { t.Errorf("Issues.IsAssignee returned %+v, want %+v", assignee, want) } } func TestIssuesService_IsAssignee_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.IsAssignee(context.Background(), "%", "r", "u") testURLParseError(t, err) } func TestIssuesService_AddAssignees(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/assignees", func(w http.ResponseWriter, r *http.Request) { var assignees struct { Assignees []string `json:"assignees,omitempty"` } json.NewDecoder(r.Body).Decode(&assignees) testMethod(t, r, "POST") want := []string{"user1", "user2"} if !reflect.DeepEqual(assignees.Assignees, want) { t.Errorf("assignees = %+v, want %+v", assignees, want) } fmt.Fprint(w, `{"number":1,"assignees":[{"login":"user1"},{"login":"user2"}]}`) }) got, _, err := client.Issues.AddAssignees(context.Background(), "o", "r", 1, []string{"user1", "user2"}) if err != nil { t.Errorf("Issues.AddAssignees returned error: %v", err) } want := &Issue{Number: Int(1), Assignees: []*User{{Login: String("user1")}, {Login: String("user2")}}} if !reflect.DeepEqual(got, want) { t.Errorf("Issues.AddAssignees = %+v, want %+v", got, want) } } func TestIssuesService_RemoveAssignees(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/assignees", func(w http.ResponseWriter, r *http.Request) { var assignees struct { Assignees []string `json:"assignees,omitempty"` } json.NewDecoder(r.Body).Decode(&assignees) testMethod(t, r, "DELETE") want := []string{"user1", "user2"} if !reflect.DeepEqual(assignees.Assignees, want) { t.Errorf("assignees = %+v, want %+v", assignees, want) } fmt.Fprint(w, `{"number":1,"assignees":[]}`) }) got, _, err := client.Issues.RemoveAssignees(context.Background(), "o", "r", 1, []string{"user1", "user2"}) if err != nil { t.Errorf("Issues.RemoveAssignees returned error: %v", err) } want := &Issue{Number: Int(1), Assignees: []*User{}} if !reflect.DeepEqual(got, want) { t.Errorf("Issues.RemoveAssignees = %+v, want %+v", got, want) } } go-github-28.1.1/github/issues_comments.go000066400000000000000000000120151353501270500205210ustar00rootroot00000000000000// 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" "time" ) // IssueComment represents a comment left on an issue. type IssueComment struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` Body *string `json:"body,omitempty"` User *User `json:"user,omitempty"` Reactions *Reactions `json:"reactions,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` // AuthorAssociation is the comment author's relationship to the issue's repository. // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". AuthorAssociation *string `json:"author_association,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` IssueURL *string `json:"issue_url,omitempty"` } func (i IssueComment) String() string { return Stringify(i) } // IssueListCommentsOptions specifies the optional parameters to the // IssuesService.ListComments method. type IssueListCommentsOptions struct { // Sort specifies how to sort comments. Possible values are: created, updated. Sort string `url:"sort,omitempty"` // Direction in which to sort comments. Possible values are: asc, desc. Direction string `url:"direction,omitempty"` // Since filters comments by time. Since time.Time `url:"since,omitempty"` ListOptions } // 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 func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opt *IssueListCommentsOptions) ([]*IssueComment, *Response, error) { var u string if number == 0 { u = fmt.Sprintf("repos/%v/%v/issues/comments", owner, repo) } else { u = fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeReactionsPreview) var comments []*IssueComment resp, err := s.client.Do(ctx, req, &comments) if err != nil { return nil, resp, err } return comments, resp, nil } // GetComment fetches the specified issue comment. // // GitHub API docs: https://developer.github.com/v3/issues/comments/#get-a-single-comment func (s *IssuesService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*IssueComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeReactionsPreview) comment := new(IssueComment) resp, err := s.client.Do(ctx, req, comment) if err != nil { return nil, resp, err } return comment, resp, nil } // CreateComment creates a new comment on the specified issue. // // GitHub API docs: https://developer.github.com/v3/issues/comments/#create-a-comment func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *IssueComment) (*IssueComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) req, err := s.client.NewRequest("POST", u, comment) if err != nil { return nil, nil, err } c := new(IssueComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // EditComment updates an issue comment. // A non-nil comment.Body must be provided. Other comment fields should be left nil. // // GitHub API docs: https://developer.github.com/v3/issues/comments/#edit-a-comment func (s *IssuesService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *IssueComment) (*IssueComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("PATCH", u, comment) if err != nil { return nil, nil, err } c := new(IssueComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // DeleteComment deletes an issue comment. // // GitHub API docs: https://developer.github.com/v3/issues/comments/#delete-a-comment func (s *IssuesService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/issues_comments_test.go000066400000000000000000000130421353501270500215610ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" "time" ) func TestIssuesService_ListComments_allIssues(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/comments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) testFormValues(t, r, values{ "sort": "updated", "direction": "desc", "since": "2002-02-10T15:30:00Z", "page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) opt := &IssueListCommentsOptions{ Sort: "updated", Direction: "desc", Since: time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC), ListOptions: ListOptions{Page: 2}, } comments, _, err := client.Issues.ListComments(context.Background(), "o", "r", 0, opt) if err != nil { t.Errorf("Issues.ListComments returned error: %v", err) } want := []*IssueComment{{ID: Int64(1)}} if !reflect.DeepEqual(comments, want) { t.Errorf("Issues.ListComments returned %+v, want %+v", comments, want) } } func TestIssuesService_ListComments_specificIssue(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/comments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) fmt.Fprint(w, `[{"id":1}]`) }) comments, _, err := client.Issues.ListComments(context.Background(), "o", "r", 1, nil) if err != nil { t.Errorf("Issues.ListComments returned error: %v", err) } want := []*IssueComment{{ID: Int64(1)}} if !reflect.DeepEqual(comments, want) { t.Errorf("Issues.ListComments returned %+v, want %+v", comments, want) } } func TestIssuesService_ListComments_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.ListComments(context.Background(), "%", "r", 1, nil) testURLParseError(t, err) } func TestIssuesService_GetComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/comments/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) fmt.Fprint(w, `{"id":1}`) }) comment, _, err := client.Issues.GetComment(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Issues.GetComment returned error: %v", err) } want := &IssueComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("Issues.GetComment returned %+v, want %+v", comment, want) } } func TestIssuesService_GetComment_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.GetComment(context.Background(), "%", "r", 1) testURLParseError(t, err) } func TestIssuesService_CreateComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &IssueComment{Body: String("b")} mux.HandleFunc("/repos/o/r/issues/1/comments", func(w http.ResponseWriter, r *http.Request) { v := new(IssueComment) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) comment, _, err := client.Issues.CreateComment(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Issues.CreateComment returned error: %v", err) } want := &IssueComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("Issues.CreateComment returned %+v, want %+v", comment, want) } } func TestIssuesService_CreateComment_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.CreateComment(context.Background(), "%", "r", 1, nil) testURLParseError(t, err) } func TestIssuesService_EditComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &IssueComment{Body: String("b")} mux.HandleFunc("/repos/o/r/issues/comments/1", func(w http.ResponseWriter, r *http.Request) { v := new(IssueComment) 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}`) }) comment, _, err := client.Issues.EditComment(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Issues.EditComment returned error: %v", err) } want := &IssueComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("Issues.EditComment returned %+v, want %+v", comment, want) } } func TestIssuesService_EditComment_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.EditComment(context.Background(), "%", "r", 1, nil) testURLParseError(t, err) } func TestIssuesService_DeleteComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/comments/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Issues.DeleteComment(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Issues.DeleteComments returned error: %v", err) } } func TestIssuesService_DeleteComment_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Issues.DeleteComment(context.Background(), "%", "r", 1) testURLParseError(t, err) } go-github-28.1.1/github/issues_events.go000066400000000000000000000130211353501270500201760ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "strings" "time" ) // IssueEvent represents an event that occurred around an Issue or Pull Request. type IssueEvent struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` // The User that generated this event. Actor *User `json:"actor,omitempty"` // Event identifies the actual type of Event that occurred. Possible // values are: // // closed // The Actor closed the issue. // If the issue was closed by commit message, CommitID holds the SHA1 hash of the commit. // // merged // The Actor merged into master a branch containing a commit mentioning the issue. // CommitID holds the SHA1 of the merge commit. // // referenced // The Actor committed to master a commit mentioning the issue in its commit message. // CommitID holds the SHA1 of the commit. // // reopened, unlocked // The Actor did that to the issue. // // locked // The Actor locked the issue. // LockReason holds the reason of locking the issue (if provided while locking). // // renamed // The Actor changed the issue title from Rename.From to Rename.To. // // mentioned // Someone unspecified @mentioned the Actor [sic] in an issue comment body. // // assigned, unassigned // The Assigner assigned the issue to or removed the assignment from the Assignee. // // labeled, unlabeled // The Actor added or removed the Label from the issue. // // milestoned, demilestoned // The Actor added or removed the issue from the Milestone. // // subscribed, unsubscribed // The Actor subscribed to or unsubscribed from notifications for an issue. // // head_ref_deleted, head_ref_restored // The pull request’s branch was deleted or restored. // // review_dismissed // The review was dismissed and `DismissedReview` will be populated below. // Event *string `json:"event,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` Issue *Issue `json:"issue,omitempty"` // Only present on certain events; see above. Assignee *User `json:"assignee,omitempty"` Assigner *User `json:"assigner,omitempty"` CommitID *string `json:"commit_id,omitempty"` Milestone *Milestone `json:"milestone,omitempty"` Label *Label `json:"label,omitempty"` Rename *Rename `json:"rename,omitempty"` LockReason *string `json:"lock_reason,omitempty"` ProjectCard *ProjectCard `json:"project_card,omitempty"` DismissedReview *DismissedReview `json:"dismissed_review,omitempty"` } // DismissedReview represents details for 'dismissed_review' events. type DismissedReview struct { // State represents the state of the dismissed review. // Possible values are: "commented", "approved", and "changes_requested". State *string `json:"state,omitempty"` ReviewID *int64 `json:"review_id,omitempty"` DismissalMessage *string `json:"dismissal_message,omitempty"` DismissalCommitID *string `json:"dismissal_commit_id,omitempty"` } // ListIssueEvents lists events for the specified issue. // // GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-an-issue func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*IssueEvent, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%v/events", owner, repo, number) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } acceptHeaders := []string{mediaTypeLockReasonPreview, mediaTypeProjectCardDetailsPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var events []*IssueEvent resp, err := s.client.Do(ctx, req, &events) if err != nil { return nil, resp, err } return events, resp, nil } // ListRepositoryEvents lists events for the specified repository. // // GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-a-repository func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var events []*IssueEvent resp, err := s.client.Do(ctx, req, &events) if err != nil { return nil, resp, err } return events, resp, nil } // GetEvent returns the specified issue event. // // GitHub API docs: https://developer.github.com/v3/issues/events/#get-a-single-event func (s *IssuesService) GetEvent(ctx context.Context, owner, repo string, id int64) (*IssueEvent, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/events/%v", owner, repo, id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } event := new(IssueEvent) resp, err := s.client.Do(ctx, req, event) if err != nil { return nil, resp, err } return event, resp, nil } // Rename contains details for 'renamed' events. type Rename struct { From *string `json:"from,omitempty"` To *string `json:"to,omitempty"` } func (r Rename) String() string { return Stringify(r) } go-github-28.1.1/github/issues_events_test.go000066400000000000000000000045561353501270500212520ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "net/http" "reflect" "strings" "testing" ) func TestIssuesService_ListIssueEvents(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeLockReasonPreview, mediaTypeProjectCardDetailsPreview} mux.HandleFunc("/repos/o/r/issues/1/events", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{ "page": "1", "per_page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} events, _, err := client.Issues.ListIssueEvents(context.Background(), "o", "r", 1, opt) if err != nil { t.Errorf("Issues.ListIssueEvents returned error: %v", err) } want := []*IssueEvent{{ID: Int64(1)}} if !reflect.DeepEqual(events, want) { t.Errorf("Issues.ListIssueEvents returned %+v, want %+v", events, want) } } func TestIssuesService_ListRepositoryEvents(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/events", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "1", "per_page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} events, _, err := client.Issues.ListRepositoryEvents(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Issues.ListRepositoryEvents returned error: %v", err) } want := []*IssueEvent{{ID: Int64(1)}} if !reflect.DeepEqual(events, want) { t.Errorf("Issues.ListRepositoryEvents returned %+v, want %+v", events, want) } } func TestIssuesService_GetEvent(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/events/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) event, _, err := client.Issues.GetEvent(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Issues.GetEvent returned error: %v", err) } want := &IssueEvent{ID: Int64(1)} if !reflect.DeepEqual(event, want) { t.Errorf("Issues.GetEvent returned %+v, want %+v", event, want) } } go-github-28.1.1/github/issues_labels.go000066400000000000000000000201161353501270500201370ustar00rootroot00000000000000// 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" ) // Label represents a GitHub label on an Issue type Label struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` Name *string `json:"name,omitempty"` Color *string `json:"color,omitempty"` Description *string `json:"description,omitempty"` Default *bool `json:"default,omitempty"` NodeID *string `json:"node_id,omitempty"` } func (l Label) String() string { return Stringify(l) } // ListLabels lists all labels for a repository. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#list-all-labels-for-this-repository func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) var labels []*Label resp, err := s.client.Do(ctx, req, &labels) if err != nil { return nil, resp, err } return labels, resp, nil } // GetLabel gets a single label. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#get-a-single-label func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, name string) (*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) label := new(Label) resp, err := s.client.Do(ctx, req, label) if err != nil { return nil, resp, err } return label, resp, nil } // CreateLabel creates a new label on the specified repository. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#create-a-label func (s *IssuesService) CreateLabel(ctx context.Context, owner string, repo string, label *Label) (*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) req, err := s.client.NewRequest("POST", u, label) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) l := new(Label) resp, err := s.client.Do(ctx, req, l) if err != nil { return nil, resp, err } return l, resp, nil } // EditLabel edits a label. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#update-a-label func (s *IssuesService) EditLabel(ctx context.Context, owner string, repo string, name string, label *Label) (*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) req, err := s.client.NewRequest("PATCH", u, label) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) l := new(Label) resp, err := s.client.Do(ctx, req, l) if err != nil { return nil, resp, err } return l, resp, nil } // DeleteLabel deletes a label. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#delete-a-label func (s *IssuesService) DeleteLabel(ctx context.Context, owner string, repo string, name string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // ListLabelsByIssue lists all labels for an issue. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#list-labels-on-an-issue func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) var labels []*Label resp, err := s.client.Do(ctx, req, &labels) if err != nil { return nil, resp, err } return labels, resp, nil } // AddLabelsToIssue adds labels to an issue. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#add-labels-to-an-issue func (s *IssuesService) AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) req, err := s.client.NewRequest("POST", u, labels) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) var l []*Label resp, err := s.client.Do(ctx, req, &l) if err != nil { return nil, resp, err } return l, resp, nil } // RemoveLabelForIssue removes a label for an issue. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#remove-a-label-from-an-issue func (s *IssuesService) RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/labels/%v", owner, repo, number, label) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) return s.client.Do(ctx, req, nil) } // ReplaceLabelsForIssue replaces all labels for an issue. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#replace-all-labels-for-an-issue func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) req, err := s.client.NewRequest("PUT", u, labels) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) var l []*Label resp, err := s.client.Do(ctx, req, &l) if err != nil { return nil, resp, err } return l, resp, nil } // RemoveLabelsForIssue removes all labels for an issue. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#remove-all-labels-from-an-issue func (s *IssuesService) RemoveLabelsForIssue(ctx context.Context, owner string, repo string, number int) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) return s.client.Do(ctx, req, nil) } // ListLabelsForMilestone lists labels for every issue in a milestone. // // GitHub API docs: https://developer.github.com/v3/issues/labels/#get-labels-for-every-issue-in-a-milestone func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones/%d/labels", owner, repo, number) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) var labels []*Label resp, err := s.client.Do(ctx, req, &labels) if err != nil { return nil, resp, err } return labels, resp, nil } go-github-28.1.1/github/issues_labels_test.go000066400000000000000000000246451353501270500212110ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestIssuesService_ListLabels(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/labels", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"name": "a"},{"name": "b"}]`) }) opt := &ListOptions{Page: 2} labels, _, err := client.Issues.ListLabels(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Issues.ListLabels returned error: %v", err) } want := []*Label{{Name: String("a")}, {Name: String("b")}} if !reflect.DeepEqual(labels, want) { t.Errorf("Issues.ListLabels returned %+v, want %+v", labels, want) } } func TestIssuesService_ListLabels_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.ListLabels(context.Background(), "%", "%", nil) testURLParseError(t, err) } func TestIssuesService_GetLabel(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/labels/n", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) fmt.Fprint(w, `{"url":"u", "name": "n", "color": "c", "description": "d"}`) }) label, _, err := client.Issues.GetLabel(context.Background(), "o", "r", "n") if err != nil { t.Errorf("Issues.GetLabel returned error: %v", err) } want := &Label{URL: String("u"), Name: String("n"), Color: String("c"), Description: String("d")} if !reflect.DeepEqual(label, want) { t.Errorf("Issues.GetLabel returned %+v, want %+v", label, want) } } func TestIssuesService_GetLabel_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.GetLabel(context.Background(), "%", "%", "%") testURLParseError(t, err) } func TestIssuesService_CreateLabel(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Label{Name: String("n")} mux.HandleFunc("/repos/o/r/labels", func(w http.ResponseWriter, r *http.Request) { v := new(Label) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"url":"u"}`) }) label, _, err := client.Issues.CreateLabel(context.Background(), "o", "r", input) if err != nil { t.Errorf("Issues.CreateLabel returned error: %v", err) } want := &Label{URL: String("u")} if !reflect.DeepEqual(label, want) { t.Errorf("Issues.CreateLabel returned %+v, want %+v", label, want) } } func TestIssuesService_CreateLabel_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.CreateLabel(context.Background(), "%", "%", nil) testURLParseError(t, err) } func TestIssuesService_EditLabel(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Label{Name: String("z")} mux.HandleFunc("/repos/o/r/labels/n", func(w http.ResponseWriter, r *http.Request) { v := new(Label) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"url":"u"}`) }) label, _, err := client.Issues.EditLabel(context.Background(), "o", "r", "n", input) if err != nil { t.Errorf("Issues.EditLabel returned error: %v", err) } want := &Label{URL: String("u")} if !reflect.DeepEqual(label, want) { t.Errorf("Issues.EditLabel returned %+v, want %+v", label, want) } } func TestIssuesService_EditLabel_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.EditLabel(context.Background(), "%", "%", "%", nil) testURLParseError(t, err) } func TestIssuesService_DeleteLabel(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/labels/n", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Issues.DeleteLabel(context.Background(), "o", "r", "n") if err != nil { t.Errorf("Issues.DeleteLabel returned error: %v", err) } } func TestIssuesService_DeleteLabel_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Issues.DeleteLabel(context.Background(), "%", "%", "%") testURLParseError(t, err) } func TestIssuesService_ListLabelsByIssue(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/labels", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"name":"a","id":1},{"name":"b","id":2}]`) }) opt := &ListOptions{Page: 2} labels, _, err := client.Issues.ListLabelsByIssue(context.Background(), "o", "r", 1, opt) if err != nil { t.Errorf("Issues.ListLabelsByIssue returned error: %v", err) } want := []*Label{ {Name: String("a"), ID: Int64(1)}, {Name: String("b"), ID: Int64(2)}, } if !reflect.DeepEqual(labels, want) { t.Errorf("Issues.ListLabelsByIssue returned %+v, want %+v", labels, want) } } func TestIssuesService_ListLabelsByIssue_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.ListLabelsByIssue(context.Background(), "%", "%", 1, nil) testURLParseError(t, err) } func TestIssuesService_AddLabelsToIssue(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := []string{"a", "b"} mux.HandleFunc("/repos/o/r/issues/1/labels", func(w http.ResponseWriter, r *http.Request) { var v []string json.NewDecoder(r.Body).Decode(&v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `[{"url":"u"}]`) }) labels, _, err := client.Issues.AddLabelsToIssue(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Issues.AddLabelsToIssue returned error: %v", err) } want := []*Label{{URL: String("u")}} if !reflect.DeepEqual(labels, want) { t.Errorf("Issues.AddLabelsToIssue returned %+v, want %+v", labels, want) } } func TestIssuesService_AddLabelsToIssue_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.AddLabelsToIssue(context.Background(), "%", "%", 1, nil) testURLParseError(t, err) } func TestIssuesService_RemoveLabelForIssue(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/labels/l", func(w http.ResponseWriter, r *http.Request) { testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) testMethod(t, r, "DELETE") }) _, err := client.Issues.RemoveLabelForIssue(context.Background(), "o", "r", 1, "l") if err != nil { t.Errorf("Issues.RemoveLabelForIssue returned error: %v", err) } } func TestIssuesService_RemoveLabelForIssue_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Issues.RemoveLabelForIssue(context.Background(), "%", "%", 1, "%") testURLParseError(t, err) } func TestIssuesService_ReplaceLabelsForIssue(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := []string{"a", "b"} mux.HandleFunc("/repos/o/r/issues/1/labels", func(w http.ResponseWriter, r *http.Request) { var v []string json.NewDecoder(r.Body).Decode(&v) testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `[{"url":"u"}]`) }) labels, _, err := client.Issues.ReplaceLabelsForIssue(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Issues.ReplaceLabelsForIssue returned error: %v", err) } want := []*Label{{URL: String("u")}} if !reflect.DeepEqual(labels, want) { t.Errorf("Issues.ReplaceLabelsForIssue returned %+v, want %+v", labels, want) } } func TestIssuesService_ReplaceLabelsForIssue_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.ReplaceLabelsForIssue(context.Background(), "%", "%", 1, nil) testURLParseError(t, err) } func TestIssuesService_RemoveLabelsForIssue(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/labels", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) }) _, err := client.Issues.RemoveLabelsForIssue(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Issues.RemoveLabelsForIssue returned error: %v", err) } } func TestIssuesService_RemoveLabelsForIssue_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Issues.RemoveLabelsForIssue(context.Background(), "%", "%", 1) testURLParseError(t, err) } func TestIssuesService_ListLabelsForMilestone(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/milestones/1/labels", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"name": "a"},{"name": "b"}]`) }) opt := &ListOptions{Page: 2} labels, _, err := client.Issues.ListLabelsForMilestone(context.Background(), "o", "r", 1, opt) if err != nil { t.Errorf("Issues.ListLabelsForMilestone returned error: %v", err) } want := []*Label{{Name: String("a")}, {Name: String("b")}} if !reflect.DeepEqual(labels, want) { t.Errorf("Issues.ListLabelsForMilestone returned %+v, want %+v", labels, want) } } func TestIssuesService_ListLabelsForMilestone_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.ListLabelsForMilestone(context.Background(), "%", "%", 1, nil) testURLParseError(t, err) } go-github-28.1.1/github/issues_milestones.go000066400000000000000000000111471353501270500210630ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "time" ) // Milestone represents a GitHub repository milestone. type Milestone struct { URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` LabelsURL *string `json:"labels_url,omitempty"` ID *int64 `json:"id,omitempty"` Number *int `json:"number,omitempty"` State *string `json:"state,omitempty"` Title *string `json:"title,omitempty"` Description *string `json:"description,omitempty"` Creator *User `json:"creator,omitempty"` OpenIssues *int `json:"open_issues,omitempty"` ClosedIssues *int `json:"closed_issues,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` ClosedAt *time.Time `json:"closed_at,omitempty"` DueOn *time.Time `json:"due_on,omitempty"` NodeID *string `json:"node_id,omitempty"` } func (m Milestone) String() string { return Stringify(m) } // MilestoneListOptions specifies the optional parameters to the // IssuesService.ListMilestones method. type MilestoneListOptions struct { // State filters milestones based on their state. Possible values are: // open, closed, all. Default is "open". State string `url:"state,omitempty"` // Sort specifies how to sort milestones. Possible values are: due_on, completeness. // Default value is "due_on". Sort string `url:"sort,omitempty"` // Direction in which to sort milestones. Possible values are: asc, desc. // Default is "asc". Direction string `url:"direction,omitempty"` ListOptions } // ListMilestones lists all milestones for a repository. // // GitHub API docs: https://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo string, opt *MilestoneListOptions) ([]*Milestone, *Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var milestones []*Milestone resp, err := s.client.Do(ctx, req, &milestones) if err != nil { return nil, resp, err } return milestones, resp, nil } // GetMilestone gets a single milestone. // // GitHub API docs: https://developer.github.com/v3/issues/milestones/#get-a-single-milestone func (s *IssuesService) GetMilestone(ctx context.Context, owner string, repo string, number int) (*Milestone, *Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } milestone := new(Milestone) resp, err := s.client.Do(ctx, req, milestone) if err != nil { return nil, resp, err } return milestone, resp, nil } // CreateMilestone creates a new milestone on the specified repository. // // GitHub API docs: https://developer.github.com/v3/issues/milestones/#create-a-milestone func (s *IssuesService) CreateMilestone(ctx context.Context, owner string, repo string, milestone *Milestone) (*Milestone, *Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) req, err := s.client.NewRequest("POST", u, milestone) if err != nil { return nil, nil, err } m := new(Milestone) resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } // EditMilestone edits a milestone. // // GitHub API docs: https://developer.github.com/v3/issues/milestones/#update-a-milestone func (s *IssuesService) EditMilestone(ctx context.Context, owner string, repo string, number int, milestone *Milestone) (*Milestone, *Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) req, err := s.client.NewRequest("PATCH", u, milestone) if err != nil { return nil, nil, err } m := new(Milestone) resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } // DeleteMilestone deletes a milestone. // // GitHub API docs: https://developer.github.com/v3/issues/milestones/#delete-a-milestone func (s *IssuesService) DeleteMilestone(ctx context.Context, owner string, repo string, number int) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/issues_milestones_test.go000066400000000000000000000113651353501270500221240ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestIssuesService_ListMilestones(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/milestones", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "state": "closed", "sort": "due_date", "direction": "asc", "page": "2", }) fmt.Fprint(w, `[{"number":1}]`) }) opt := &MilestoneListOptions{"closed", "due_date", "asc", ListOptions{Page: 2}} milestones, _, err := client.Issues.ListMilestones(context.Background(), "o", "r", opt) if err != nil { t.Errorf("IssuesService.ListMilestones returned error: %v", err) } want := []*Milestone{{Number: Int(1)}} if !reflect.DeepEqual(milestones, want) { t.Errorf("IssuesService.ListMilestones returned %+v, want %+v", milestones, want) } } func TestIssuesService_ListMilestones_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.ListMilestones(context.Background(), "%", "r", nil) testURLParseError(t, err) } func TestIssuesService_GetMilestone(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"number":1}`) }) milestone, _, err := client.Issues.GetMilestone(context.Background(), "o", "r", 1) if err != nil { t.Errorf("IssuesService.GetMilestone returned error: %v", err) } want := &Milestone{Number: Int(1)} if !reflect.DeepEqual(milestone, want) { t.Errorf("IssuesService.GetMilestone returned %+v, want %+v", milestone, want) } } func TestIssuesService_GetMilestone_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.GetMilestone(context.Background(), "%", "r", 1) testURLParseError(t, err) } func TestIssuesService_CreateMilestone(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Milestone{Title: String("t")} mux.HandleFunc("/repos/o/r/milestones", func(w http.ResponseWriter, r *http.Request) { v := new(Milestone) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"number":1}`) }) milestone, _, err := client.Issues.CreateMilestone(context.Background(), "o", "r", input) if err != nil { t.Errorf("IssuesService.CreateMilestone returned error: %v", err) } want := &Milestone{Number: Int(1)} if !reflect.DeepEqual(milestone, want) { t.Errorf("IssuesService.CreateMilestone returned %+v, want %+v", milestone, want) } } func TestIssuesService_CreateMilestone_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.CreateMilestone(context.Background(), "%", "r", nil) testURLParseError(t, err) } func TestIssuesService_EditMilestone(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Milestone{Title: String("t")} mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) { v := new(Milestone) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"number":1}`) }) milestone, _, err := client.Issues.EditMilestone(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("IssuesService.EditMilestone returned error: %v", err) } want := &Milestone{Number: Int(1)} if !reflect.DeepEqual(milestone, want) { t.Errorf("IssuesService.EditMilestone returned %+v, want %+v", milestone, want) } } func TestIssuesService_EditMilestone_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.EditMilestone(context.Background(), "%", "r", 1, nil) testURLParseError(t, err) } func TestIssuesService_DeleteMilestone(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Issues.DeleteMilestone(context.Background(), "o", "r", 1) if err != nil { t.Errorf("IssuesService.DeleteMilestone returned error: %v", err) } } func TestIssuesService_DeleteMilestone_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Issues.DeleteMilestone(context.Background(), "%", "r", 1) testURLParseError(t, err) } go-github-28.1.1/github/issues_test.go000066400000000000000000000223531353501270500176610ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "strings" "testing" "time" ) func TestIssuesService_List_all(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} mux.HandleFunc("/issues", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{ "filter": "all", "state": "closed", "labels": "a,b", "sort": "updated", "direction": "asc", "since": "2002-02-10T15:30:00Z", "page": "1", "per_page": "2", }) fmt.Fprint(w, `[{"number":1}]`) }) opt := &IssueListOptions{ "all", "closed", []string{"a", "b"}, "updated", "asc", time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC), ListOptions{Page: 1, PerPage: 2}, } issues, _, err := client.Issues.List(context.Background(), true, opt) if err != nil { t.Errorf("Issues.List returned error: %v", err) } want := []*Issue{{Number: Int(1)}} if !reflect.DeepEqual(issues, want) { t.Errorf("Issues.List returned %+v, want %+v", issues, want) } } func TestIssuesService_List_owned(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} mux.HandleFunc("/user/issues", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `[{"number":1}]`) }) issues, _, err := client.Issues.List(context.Background(), false, nil) if err != nil { t.Errorf("Issues.List returned error: %v", err) } want := []*Issue{{Number: Int(1)}} if !reflect.DeepEqual(issues, want) { t.Errorf("Issues.List returned %+v, want %+v", issues, want) } } func TestIssuesService_ListByOrg(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} mux.HandleFunc("/orgs/o/issues", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `[{"number":1}]`) }) issues, _, err := client.Issues.ListByOrg(context.Background(), "o", nil) if err != nil { t.Errorf("Issues.ListByOrg returned error: %v", err) } want := []*Issue{{Number: Int(1)}} if !reflect.DeepEqual(issues, want) { t.Errorf("Issues.List returned %+v, want %+v", issues, want) } } func TestIssuesService_ListByOrg_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.ListByOrg(context.Background(), "%", nil) testURLParseError(t, err) } func TestIssuesService_ListByRepo(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeIntegrationPreview} mux.HandleFunc("/repos/o/r/issues", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{ "milestone": "*", "state": "closed", "assignee": "a", "creator": "c", "mentioned": "m", "labels": "a,b", "sort": "updated", "direction": "asc", "since": "2002-02-10T15:30:00Z", }) fmt.Fprint(w, `[{"number":1}]`) }) opt := &IssueListByRepoOptions{ "*", "closed", "a", "c", "m", []string{"a", "b"}, "updated", "asc", time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC), ListOptions{0, 0}, } issues, _, err := client.Issues.ListByRepo(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Issues.ListByOrg returned error: %v", err) } want := []*Issue{{Number: Int(1)}} if !reflect.DeepEqual(issues, want) { t.Errorf("Issues.List returned %+v, want %+v", issues, want) } } func TestIssuesService_ListByRepo_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.ListByRepo(context.Background(), "%", "r", nil) testURLParseError(t, err) } func TestIssuesService_Get(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} mux.HandleFunc("/repos/o/r/issues/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `{"number":1, "labels": [{"url": "u", "name": "n", "color": "c"}]}`) }) issue, _, err := client.Issues.Get(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Issues.Get returned error: %v", err) } want := &Issue{ Number: Int(1), Labels: []Label{{ URL: String("u"), Name: String("n"), Color: String("c"), }}, } if !reflect.DeepEqual(issue, want) { t.Errorf("Issues.Get returned %+v, want %+v", issue, want) } } func TestIssuesService_Get_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.Get(context.Background(), "%", "r", 1) testURLParseError(t, err) } func TestIssuesService_Create(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &IssueRequest{ Title: String("t"), Body: String("b"), Assignee: String("a"), Labels: &[]string{"l1", "l2"}, } mux.HandleFunc("/repos/o/r/issues", func(w http.ResponseWriter, r *http.Request) { v := new(IssueRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"number":1}`) }) issue, _, err := client.Issues.Create(context.Background(), "o", "r", input) if err != nil { t.Errorf("Issues.Create returned error: %v", err) } want := &Issue{Number: Int(1)} if !reflect.DeepEqual(issue, want) { t.Errorf("Issues.Create returned %+v, want %+v", issue, want) } } func TestIssuesService_Create_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.Create(context.Background(), "%", "r", nil) testURLParseError(t, err) } func TestIssuesService_Edit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &IssueRequest{Title: String("t")} mux.HandleFunc("/repos/o/r/issues/1", func(w http.ResponseWriter, r *http.Request) { v := new(IssueRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"number":1}`) }) issue, _, err := client.Issues.Edit(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Issues.Edit returned error: %v", err) } want := &Issue{Number: Int(1)} if !reflect.DeepEqual(issue, want) { t.Errorf("Issues.Edit returned %+v, want %+v", issue, want) } } func TestIssuesService_Edit_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Issues.Edit(context.Background(), "%", "r", 1, nil) testURLParseError(t, err) } func TestIssuesService_Lock(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/lock", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") w.WriteHeader(http.StatusNoContent) }) if _, err := client.Issues.Lock(context.Background(), "o", "r", 1, nil); err != nil { t.Errorf("Issues.Lock returned error: %v", err) } } func TestIssuesService_LockWithReason(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/lock", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeLockReasonPreview) w.WriteHeader(http.StatusNoContent) }) opt := &LockIssueOptions{LockReason: "off-topic"} if _, err := client.Issues.Lock(context.Background(), "o", "r", 1, opt); err != nil { t.Errorf("Issues.Lock returned error: %v", err) } } func TestIssuesService_Unlock(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/lock", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) if _, err := client.Issues.Unlock(context.Background(), "o", "r", 1); err != nil { t.Errorf("Issues.Unlock returned error: %v", err) } } func TestIsPullRequest(t *testing.T) { i := new(Issue) if i.IsPullRequest() == true { t.Errorf("expected i.IsPullRequest (%v) to return false, got true", i) } i.PullRequestLinks = &PullRequestLinks{URL: String("http://example.com")} if i.IsPullRequest() == false { t.Errorf("expected i.IsPullRequest (%v) to return true, got false", i) } } go-github-28.1.1/github/issues_timeline.go000066400000000000000000000117441353501270500205120ustar00rootroot00000000000000// 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" "strings" "time" ) // Timeline represents an event that occurred around an Issue or Pull Request. // // It is similar to an IssueEvent but may contain more information. // GitHub API docs: https://developer.github.com/v3/issues/timeline/ type Timeline struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` CommitURL *string `json:"commit_url,omitempty"` // The User object that generated the event. Actor *User `json:"actor,omitempty"` // Event identifies the actual type of Event that occurred. Possible values // are: // // assigned // The issue was assigned to the assignee. // // closed // The issue was closed by the actor. When the commit_id is present, it // identifies the commit that closed the issue using "closes / fixes #NN" // syntax. // // commented // A comment was added to the issue. // // committed // A commit was added to the pull request's 'HEAD' branch. Only provided // for pull requests. // // cross-referenced // The issue was referenced from another issue. The 'source' attribute // contains the 'id', 'actor', and 'url' of the reference's source. // // demilestoned // The issue was removed from a milestone. // // head_ref_deleted // The pull request's branch was deleted. // // head_ref_restored // The pull request's branch was restored. // // labeled // A label was added to the issue. // // locked // The issue was locked by the actor. // // mentioned // The actor was @mentioned in an issue body. // // merged // The issue was merged by the actor. The 'commit_id' attribute is the // SHA1 of the HEAD commit that was merged. // // milestoned // The issue was added to a milestone. // // referenced // The issue was referenced from a commit message. The 'commit_id' // attribute is the commit SHA1 of where that happened. // // renamed // The issue title was changed. // // reopened // The issue was reopened by the actor. // // subscribed // The actor subscribed to receive notifications for an issue. // // unassigned // The assignee was unassigned from the issue. // // unlabeled // A label was removed from the issue. // // unlocked // The issue was unlocked by the actor. // // unsubscribed // The actor unsubscribed to stop receiving notifications for an issue. // Event *string `json:"event,omitempty"` // The string SHA of a commit that referenced this Issue or Pull Request. CommitID *string `json:"commit_id,omitempty"` // The timestamp indicating when the event occurred. CreatedAt *time.Time `json:"created_at,omitempty"` // The Label object including `name` and `color` attributes. Only provided for // 'labeled' and 'unlabeled' events. Label *Label `json:"label,omitempty"` // The User object which was assigned to (or unassigned from) this Issue or // Pull Request. Only provided for 'assigned' and 'unassigned' events. Assignee *User `json:"assignee,omitempty"` // The Milestone object including a 'title' attribute. // Only provided for 'milestoned' and 'demilestoned' events. Milestone *Milestone `json:"milestone,omitempty"` // The 'id', 'actor', and 'url' for the source of a reference from another issue. // Only provided for 'cross-referenced' events. Source *Source `json:"source,omitempty"` // An object containing rename details including 'from' and 'to' attributes. // Only provided for 'renamed' events. Rename *Rename `json:"rename,omitempty"` ProjectCard *ProjectCard `json:"project_card,omitempty"` } // Source represents a reference's source. type Source struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` Actor *User `json:"actor,omitempty"` Type *string `json:"type,omitempty"` Issue *Issue `json:"issue,omitempty"` } // ListIssueTimeline lists events for the specified issue. // // GitHub API docs: https://developer.github.com/v3/issues/timeline/#list-events-for-an-issue func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*Timeline, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%v/timeline", owner, repo, number) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeTimelinePreview, mediaTypeProjectCardDetailsPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var events []*Timeline resp, err := s.client.Do(ctx, req, &events) return events, resp, err } go-github-28.1.1/github/issues_timeline_test.go000066400000000000000000000021561353501270500215460ustar00rootroot00000000000000// 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" "reflect" "strings" "testing" ) func TestIssuesService_ListIssueTimeline(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeTimelinePreview, mediaTypeProjectCardDetailsPreview} mux.HandleFunc("/repos/o/r/issues/1/timeline", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{ "page": "1", "per_page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 1, PerPage: 2} events, _, err := client.Issues.ListIssueTimeline(context.Background(), "o", "r", 1, opt) if err != nil { t.Errorf("Issues.ListIssueTimeline returned error: %v", err) } want := []*Timeline{{ID: Int64(1)}} if !reflect.DeepEqual(events, want) { t.Errorf("Issues.ListIssueTimeline = %+v, want %+v", events, want) } } go-github-28.1.1/github/licenses.go000066400000000000000000000054371353501270500171200ustar00rootroot00000000000000// 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" ) // LicensesService handles communication with the license related // methods of the GitHub API. // // GitHub API docs: https://developer.github.com/v3/licenses/ type LicensesService service // RepositoryLicense represents the license for a repository. type RepositoryLicense struct { Name *string `json:"name,omitempty"` Path *string `json:"path,omitempty"` SHA *string `json:"sha,omitempty"` Size *int `json:"size,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` GitURL *string `json:"git_url,omitempty"` DownloadURL *string `json:"download_url,omitempty"` Type *string `json:"type,omitempty"` Content *string `json:"content,omitempty"` Encoding *string `json:"encoding,omitempty"` License *License `json:"license,omitempty"` } func (l RepositoryLicense) String() string { return Stringify(l) } // License represents an open source license. type License struct { Key *string `json:"key,omitempty"` Name *string `json:"name,omitempty"` URL *string `json:"url,omitempty"` SPDXID *string `json:"spdx_id,omitempty"` HTMLURL *string `json:"html_url,omitempty"` Featured *bool `json:"featured,omitempty"` Description *string `json:"description,omitempty"` Implementation *string `json:"implementation,omitempty"` Permissions *[]string `json:"permissions,omitempty"` Conditions *[]string `json:"conditions,omitempty"` Limitations *[]string `json:"limitations,omitempty"` Body *string `json:"body,omitempty"` } func (l License) String() string { return Stringify(l) } // List popular open source licenses. // // GitHub API docs: https://developer.github.com/v3/licenses/#list-all-licenses func (s *LicensesService) List(ctx context.Context) ([]*License, *Response, error) { req, err := s.client.NewRequest("GET", "licenses", nil) if err != nil { return nil, nil, err } var licenses []*License resp, err := s.client.Do(ctx, req, &licenses) if err != nil { return nil, resp, err } return licenses, resp, nil } // Get extended metadata for one license. // // GitHub API docs: https://developer.github.com/v3/licenses/#get-an-individual-license func (s *LicensesService) Get(ctx context.Context, licenseName string) (*License, *Response, error) { u := fmt.Sprintf("licenses/%s", licenseName) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } license := new(License) resp, err := s.client.Do(ctx, req, license) if err != nil { return nil, resp, err } return license, resp, nil } go-github-28.1.1/github/licenses_test.go000066400000000000000000000034061353501270500201510ustar00rootroot00000000000000// 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" "net/http" "reflect" "testing" ) func TestLicensesService_List(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/licenses", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"key":"mit","name":"MIT","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","featured":true}]`) }) licenses, _, err := client.Licenses.List(context.Background()) if err != nil { t.Errorf("Licenses.List returned error: %v", err) } want := []*License{{ Key: String("mit"), Name: String("MIT"), SPDXID: String("MIT"), URL: String("https://api.github.com/licenses/mit"), Featured: Bool(true), }} if !reflect.DeepEqual(licenses, want) { t.Errorf("Licenses.List returned %+v, want %+v", licenses, want) } } func TestLicensesService_Get(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/licenses/mit", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"key":"mit","name":"MIT"}`) }) license, _, err := client.Licenses.Get(context.Background(), "mit") if err != nil { t.Errorf("Licenses.Get returned error: %v", err) } want := &License{Key: String("mit"), Name: String("MIT")} if !reflect.DeepEqual(license, want) { t.Errorf("Licenses.Get returned %+v, want %+v", license, want) } } func TestLicensesService_Get_invalidTemplate(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Licenses.Get(context.Background(), "%") testURLParseError(t, err) } go-github-28.1.1/github/messages.go000066400000000000000000000221361353501270500171150ustar00rootroot00000000000000// 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. // This file provides functions for validating payloads from GitHub Webhooks. // GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github package github import ( "crypto/hmac" "crypto/sha1" "crypto/sha256" "crypto/sha512" "encoding/hex" "encoding/json" "errors" "fmt" "hash" "io/ioutil" "net/http" "net/url" "strings" ) const ( // sha1Prefix is the prefix used by GitHub before the HMAC hexdigest. sha1Prefix = "sha1" // sha256Prefix and sha512Prefix are provided for future compatibility. sha256Prefix = "sha256" sha512Prefix = "sha512" // signatureHeader is the GitHub header key used to pass the HMAC hexdigest. signatureHeader = "X-Hub-Signature" // eventTypeHeader is the GitHub header key used to pass the event type. eventTypeHeader = "X-Github-Event" // deliveryIDHeader is the GitHub header key used to pass the unique ID for the webhook event. deliveryIDHeader = "X-Github-Delivery" ) var ( // eventTypeMapping maps webhooks types to their corresponding go-github struct types. eventTypeMapping = map[string]string{ "check_run": "CheckRunEvent", "check_suite": "CheckSuiteEvent", "commit_comment": "CommitCommentEvent", "create": "CreateEvent", "delete": "DeleteEvent", "deploy_key": "DeployKeyEvent", "deployment": "DeploymentEvent", "deployment_status": "DeploymentStatusEvent", "fork": "ForkEvent", "gollum": "GollumEvent", "installation": "InstallationEvent", "installation_repositories": "InstallationRepositoriesEvent", "issue_comment": "IssueCommentEvent", "issues": "IssuesEvent", "label": "LabelEvent", "marketplace_purchase": "MarketplacePurchaseEvent", "member": "MemberEvent", "membership": "MembershipEvent", "meta": "MetaEvent", "milestone": "MilestoneEvent", "organization": "OrganizationEvent", "org_block": "OrgBlockEvent", "page_build": "PageBuildEvent", "ping": "PingEvent", "project": "ProjectEvent", "project_card": "ProjectCardEvent", "project_column": "ProjectColumnEvent", "public": "PublicEvent", "pull_request_review": "PullRequestReviewEvent", "pull_request_review_comment": "PullRequestReviewCommentEvent", "pull_request": "PullRequestEvent", "push": "PushEvent", "repository": "RepositoryEvent", "repository_vulnerability_alert": "RepositoryVulnerabilityAlertEvent", "release": "ReleaseEvent", "star": "StarEvent", "status": "StatusEvent", "team": "TeamEvent", "team_add": "TeamAddEvent", "watch": "WatchEvent", } ) // genMAC generates the HMAC signature for a message provided the secret key // and hashFunc. func genMAC(message, key []byte, hashFunc func() hash.Hash) []byte { mac := hmac.New(hashFunc, key) mac.Write(message) return mac.Sum(nil) } // checkMAC reports whether messageMAC is a valid HMAC tag for message. func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool { expectedMAC := genMAC(message, key, hashFunc) return hmac.Equal(messageMAC, expectedMAC) } // messageMAC returns the hex-decoded HMAC tag from the signature and its // corresponding hash function. func messageMAC(signature string) ([]byte, func() hash.Hash, error) { if signature == "" { return nil, nil, errors.New("missing signature") } sigParts := strings.SplitN(signature, "=", 2) if len(sigParts) != 2 { return nil, nil, fmt.Errorf("error parsing signature %q", signature) } var hashFunc func() hash.Hash switch sigParts[0] { case sha1Prefix: hashFunc = sha1.New case sha256Prefix: hashFunc = sha256.New case sha512Prefix: hashFunc = sha512.New default: return nil, nil, fmt.Errorf("unknown hash type prefix: %q", sigParts[0]) } buf, err := hex.DecodeString(sigParts[1]) if err != nil { return nil, nil, fmt.Errorf("error decoding signature %q: %v", signature, err) } return buf, hashFunc, nil } // ValidatePayload validates an incoming GitHub Webhook event request // and returns the (JSON) payload. // The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded". // If the Content-Type is neither then an error is returned. // secretToken is the GitHub Webhook secret token. // If your webhook does not contain a secret token, you can pass nil or an empty slice. // This is intended for local development purposes only and all webhooks should ideally set up a secret token. // // Example usage: // // func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { // payload, err := github.ValidatePayload(r, s.webhookSecretKey) // if err != nil { ... } // // Process payload... // } // func ValidatePayload(r *http.Request, secretToken []byte) (payload []byte, err error) { var body []byte // Raw body that GitHub uses to calculate the signature. switch ct := r.Header.Get("Content-Type"); ct { case "application/json": var err error if body, err = ioutil.ReadAll(r.Body); err != nil { return nil, err } // If the content type is application/json, // the JSON payload is just the original body. payload = body case "application/x-www-form-urlencoded": // payloadFormParam is the name of the form parameter that the JSON payload // will be in if a webhook has its content type set to application/x-www-form-urlencoded. const payloadFormParam = "payload" var err error if body, err = ioutil.ReadAll(r.Body); err != nil { return nil, err } // If the content type is application/x-www-form-urlencoded, // the JSON payload will be under the "payload" form param. form, err := url.ParseQuery(string(body)) if err != nil { return nil, err } payload = []byte(form.Get(payloadFormParam)) default: return nil, fmt.Errorf("Webhook request has unsupported Content-Type %q", ct) } // Only validate the signature if a secret token exists. This is intended for // local development only and all webhooks should ideally set up a secret token. if len(secretToken) > 0 { sig := r.Header.Get(signatureHeader) if err := ValidateSignature(sig, body, secretToken); err != nil { return nil, err } } return payload, nil } // ValidateSignature validates the signature for the given payload. // signature is the GitHub hash signature delivered in the X-Hub-Signature header. // payload is the JSON payload sent by GitHub Webhooks. // secretToken is the GitHub Webhook secret token. // // GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github func ValidateSignature(signature string, payload, secretToken []byte) error { messageMAC, hashFunc, err := messageMAC(signature) if err != nil { return err } if !checkMAC(payload, messageMAC, secretToken, hashFunc) { return errors.New("payload signature check failed") } return nil } // WebHookType returns the event type of webhook request r. // // GitHub API docs: https://developer.github.com/v3/repos/hooks/#webhook-headers func WebHookType(r *http.Request) string { return r.Header.Get(eventTypeHeader) } // DeliveryID returns the unique delivery ID of webhook request r. // // GitHub API docs: https://developer.github.com/v3/repos/hooks/#webhook-headers func DeliveryID(r *http.Request) string { return r.Header.Get(deliveryIDHeader) } // ParseWebHook parses the event payload. For recognized event types, a // value of the corresponding struct type will be returned (as returned // by Event.ParsePayload()). An error will be returned for unrecognized event // types. // // Example usage: // // func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { // payload, err := github.ValidatePayload(r, s.webhookSecretKey) // if err != nil { ... } // event, err := github.ParseWebHook(github.WebHookType(r), payload) // if err != nil { ... } // switch event := event.(type) { // case *github.CommitCommentEvent: // processCommitCommentEvent(event) // case *github.CreateEvent: // processCreateEvent(event) // ... // } // } // func ParseWebHook(messageType string, payload []byte) (interface{}, error) { eventType, ok := eventTypeMapping[messageType] if !ok { return nil, fmt.Errorf("unknown X-Github-Event in message: %v", messageType) } event := Event{ Type: &eventType, RawPayload: (*json.RawMessage)(&payload), } return event.ParsePayload() } go-github-28.1.1/github/messages_test.go000066400000000000000000000215431353501270500201550ustar00rootroot00000000000000// 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 ( "bytes" "encoding/json" "net/http" "net/url" "reflect" "strings" "testing" ) func TestValidatePayload(t *testing.T) { const defaultBody = `{"yo":true}` // All tests below use the default request body and signature. const defaultSignature = "sha1=126f2c800419c60137ce748d7672e77b65cf16d6" secretKey := []byte("0123456789abcdef") tests := []struct { signature string eventID string event string wantEventID string wantEvent string wantPayload string }{ // The following tests generate expected errors: {}, // Missing signature {signature: "yo"}, // Missing signature prefix {signature: "sha1=yo"}, // Signature not hex string {signature: "sha1=012345"}, // Invalid signature // The following tests expect err=nil: { signature: defaultSignature, eventID: "dead-beef", event: "ping", wantEventID: "dead-beef", wantEvent: "ping", wantPayload: defaultBody, }, { signature: defaultSignature, event: "ping", wantEvent: "ping", wantPayload: defaultBody, }, { signature: "sha256=b1f8020f5b4cd42042f807dd939015c4a418bc1ff7f604dd55b0a19b5d953d9b", event: "ping", wantEvent: "ping", wantPayload: defaultBody, }, { signature: "sha512=8456767023c1195682e182a23b3f5d19150ecea598fde8cb85918f7281b16079471b1329f92b912c4d8bd7455cb159777db8f29608b20c7c87323ba65ae62e1f", event: "ping", wantEvent: "ping", wantPayload: defaultBody, }, } for _, test := range tests { buf := bytes.NewBufferString(defaultBody) req, err := http.NewRequest("GET", "http://localhost/event", buf) if err != nil { t.Fatalf("NewRequest: %v", err) } if test.signature != "" { req.Header.Set(signatureHeader, test.signature) } req.Header.Set("Content-Type", "application/json") got, err := ValidatePayload(req, secretKey) if err != nil { if test.wantPayload != "" { t.Errorf("ValidatePayload(%#v): err = %v, want nil", test, err) } continue } if string(got) != test.wantPayload { t.Errorf("ValidatePayload = %q, want %q", got, test.wantPayload) } } } func TestValidatePayload_FormGet(t *testing.T) { payload := `{"yo":true}` signature := "sha1=3374ef144403e8035423b23b02e2c9d7a4c50368" secretKey := []byte("0123456789abcdef") form := url.Values{} form.Add("payload", payload) req, err := http.NewRequest("POST", "http://localhost/event", strings.NewReader(form.Encode())) if err != nil { t.Fatalf("NewRequest: %v", err) } req.PostForm = form req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set(signatureHeader, signature) got, err := ValidatePayload(req, secretKey) if err != nil { t.Errorf("ValidatePayload(%#v): err = %v, want nil", payload, err) } if string(got) != payload { t.Errorf("ValidatePayload = %q, want %q", got, payload) } // check that if payload is invalid we get error req.Header.Set(signatureHeader, "invalid signature") if _, err = ValidatePayload(req, []byte{0}); err == nil { t.Error("ValidatePayload = nil, want err") } } func TestValidatePayload_FormPost(t *testing.T) { payload := `{"yo":true}` signature := "sha1=3374ef144403e8035423b23b02e2c9d7a4c50368" secretKey := []byte("0123456789abcdef") form := url.Values{} form.Set("payload", payload) buf := bytes.NewBufferString(form.Encode()) req, err := http.NewRequest("POST", "http://localhost/event", buf) if err != nil { t.Fatalf("NewRequest: %v", err) } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set(signatureHeader, signature) got, err := ValidatePayload(req, secretKey) if err != nil { t.Errorf("ValidatePayload(%#v): err = %v, want nil", payload, err) } if string(got) != payload { t.Errorf("ValidatePayload = %q, want %q", got, payload) } // check that if payload is invalid we get error req.Header.Set(signatureHeader, "invalid signature") if _, err = ValidatePayload(req, []byte{0}); err == nil { t.Error("ValidatePayload = nil, want err") } } func TestValidatePayload_InvalidContentType(t *testing.T) { req, err := http.NewRequest("POST", "http://localhost/event", nil) if err != nil { t.Fatalf("NewRequest: %v", err) } req.Header.Set("Content-Type", "invalid content type") if _, err = ValidatePayload(req, nil); err == nil { t.Error("ValidatePayload = nil, want err") } } func TestValidatePayload_NoSecretKey(t *testing.T) { payload := `{"yo":true}` form := url.Values{} form.Set("payload", payload) buf := bytes.NewBufferString(form.Encode()) req, err := http.NewRequest("POST", "http://localhost/event", buf) if err != nil { t.Fatalf("NewRequest: %v", err) } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") got, err := ValidatePayload(req, nil) if err != nil { t.Errorf("ValidatePayload(%#v): err = %v, want nil", payload, err) } if string(got) != payload { t.Errorf("ValidatePayload = %q, want %q", got, payload) } } func TestParseWebHook(t *testing.T) { tests := []struct { payload interface{} messageType string }{ { payload: &CheckRunEvent{}, messageType: "check_run", }, { payload: &CheckSuiteEvent{}, messageType: "check_suite", }, { payload: &CommitCommentEvent{}, messageType: "commit_comment", }, { payload: &CreateEvent{}, messageType: "create", }, { payload: &DeleteEvent{}, messageType: "delete", }, { payload: &DeployKeyEvent{}, messageType: "deploy_key", }, { payload: &DeploymentEvent{}, messageType: "deployment", }, { payload: &DeploymentStatusEvent{}, messageType: "deployment_status", }, { payload: &ForkEvent{}, messageType: "fork", }, { payload: &GollumEvent{}, messageType: "gollum", }, { payload: &InstallationEvent{}, messageType: "installation", }, { payload: &InstallationRepositoriesEvent{}, messageType: "installation_repositories", }, { payload: &IssueCommentEvent{}, messageType: "issue_comment", }, { payload: &IssuesEvent{}, messageType: "issues", }, { payload: &LabelEvent{}, messageType: "label", }, { payload: &MarketplacePurchaseEvent{}, messageType: "marketplace_purchase", }, { payload: &MemberEvent{}, messageType: "member", }, { payload: &MembershipEvent{}, messageType: "membership", }, { payload: &MetaEvent{}, messageType: "meta", }, { payload: &MilestoneEvent{}, messageType: "milestone", }, { payload: &OrganizationEvent{}, messageType: "organization", }, { payload: &OrgBlockEvent{}, messageType: "org_block", }, { payload: &PageBuildEvent{}, messageType: "page_build", }, { payload: &PingEvent{}, messageType: "ping", }, { payload: &ProjectEvent{}, messageType: "project", }, { payload: &ProjectCardEvent{}, messageType: "project_card", }, { payload: &ProjectColumnEvent{}, messageType: "project_column", }, { payload: &PublicEvent{}, messageType: "public", }, { payload: &PullRequestEvent{}, messageType: "pull_request", }, { payload: &PullRequestReviewEvent{}, messageType: "pull_request_review", }, { payload: &PullRequestReviewCommentEvent{}, messageType: "pull_request_review_comment", }, { payload: &PushEvent{}, messageType: "push", }, { payload: &ReleaseEvent{}, messageType: "release", }, { payload: &RepositoryEvent{}, messageType: "repository", }, { payload: &RepositoryVulnerabilityAlertEvent{}, messageType: "repository_vulnerability_alert", }, { payload: &StarEvent{}, messageType: "star", }, { payload: &StatusEvent{}, messageType: "status", }, { payload: &TeamEvent{}, messageType: "team", }, { payload: &TeamAddEvent{}, messageType: "team_add", }, { payload: &WatchEvent{}, messageType: "watch", }, } for _, test := range tests { p, err := json.Marshal(test.payload) if err != nil { t.Fatalf("Marshal(%#v): %v", test.payload, err) } got, err := ParseWebHook(test.messageType, p) if err != nil { t.Fatalf("ParseWebHook: %v", err) } if want := test.payload; !reflect.DeepEqual(got, want) { t.Errorf("ParseWebHook(%#v, %#v) = %#v, want %#v", test.messageType, p, got, want) } } } func TestDeliveryID(t *testing.T) { id := "8970a780-244e-11e7-91ca-da3aabcb9793" req, err := http.NewRequest("POST", "http://localhost", nil) if err != nil { t.Fatalf("DeliveryID: %v", err) } req.Header.Set("X-Github-Delivery", id) got := DeliveryID(req) if got != id { t.Errorf("DeliveryID(%#v) = %q, want %q", req, got, id) } } go-github-28.1.1/github/migrations.go000066400000000000000000000166531353501270500174710ustar00rootroot00000000000000// 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" "errors" "fmt" "net/http" "strings" ) // MigrationService provides access to the migration related functions // in the GitHub API. // // GitHub API docs: https://developer.github.com/v3/migration/ type MigrationService service // Migration represents a GitHub migration (archival). type Migration struct { ID *int64 `json:"id,omitempty"` GUID *string `json:"guid,omitempty"` // State is the current state of a migration. // Possible values are: // "pending" which means the migration hasn't started yet, // "exporting" which means the migration is in progress, // "exported" which means the migration finished successfully, or // "failed" which means the migration failed. State *string `json:"state,omitempty"` // LockRepositories indicates whether repositories are locked (to prevent // manipulation) while migrating data. LockRepositories *bool `json:"lock_repositories,omitempty"` // ExcludeAttachments indicates whether attachments should be excluded from // the migration (to reduce migration archive file size). ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` URL *string `json:"url,omitempty"` CreatedAt *string `json:"created_at,omitempty"` UpdatedAt *string `json:"updated_at,omitempty"` Repositories []*Repository `json:"repositories,omitempty"` } func (m Migration) String() string { return Stringify(m) } // MigrationOptions specifies the optional parameters to Migration methods. type MigrationOptions struct { // LockRepositories indicates whether repositories should be locked (to prevent // manipulation) while migrating data. LockRepositories bool // ExcludeAttachments indicates whether attachments should be excluded from // the migration (to reduce migration archive file size). ExcludeAttachments bool } // startMigration represents the body of a StartMigration request. type startMigration struct { // Repositories is a slice of repository names to migrate. Repositories []string `json:"repositories,omitempty"` // LockRepositories indicates whether repositories should be locked (to prevent // manipulation) while migrating data. LockRepositories *bool `json:"lock_repositories,omitempty"` // ExcludeAttachments indicates whether attachments should be excluded from // the migration (to reduce migration archive file size). ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` } // 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 func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opt *MigrationOptions) (*Migration, *Response, error) { u := fmt.Sprintf("orgs/%v/migrations", org) body := &startMigration{Repositories: repos} if opt != nil { body.LockRepositories = Bool(opt.LockRepositories) body.ExcludeAttachments = Bool(opt.ExcludeAttachments) } req, err := s.client.NewRequest("POST", u, body) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) m := &Migration{} resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } // ListMigrations lists the most recent migrations. // // GitHub API docs: https://developer.github.com/v3/migration/migrations/#get-a-list-of-migrations func (s *MigrationService) ListMigrations(ctx context.Context, org string) ([]*Migration, *Response, error) { u := fmt.Sprintf("orgs/%v/migrations", org) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) var m []*Migration resp, err := s.client.Do(ctx, req, &m) if err != nil { return nil, resp, err } return m, resp, nil } // 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 func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) { u := fmt.Sprintf("orgs/%v/migrations/%v", org, id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) m := &Migration{} resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } // 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 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) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return "", err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) s.client.clientMu.Lock() defer s.client.clientMu.Unlock() // Disable the redirect mechanism because AWS fails if the GitHub auth token is provided. var loc string saveRedirect := s.client.client.CheckRedirect s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { loc = req.URL.String() return errors.New("disable redirect") } defer func() { s.client.client.CheckRedirect = saveRedirect }() _, err = s.client.Do(ctx, req, nil) // expect error from disable redirect if err == nil { return "", errors.New("expected redirect, none provided") } if !strings.Contains(err.Error(), "disable redirect") { return "", err } return loc, nil } // 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 func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) { u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) return s.client.Do(ctx, req, nil) } // UnlockRepo unlocks a repository that was locked for migration. // id is the migration ID. // 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 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) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/migrations_source_import.go000066400000000000000000000306661353501270500224430ustar00rootroot00000000000000// 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" ) // Import represents a repository import request. type Import struct { // The URL of the originating repository. VCSURL *string `json:"vcs_url,omitempty"` // The originating VCS type. Can be one of 'subversion', 'git', // 'mercurial', or 'tfvc'. Without this parameter, the import job will // take additional time to detect the VCS type before beginning the // import. This detection step will be reflected in the response. VCS *string `json:"vcs,omitempty"` // VCSUsername and VCSPassword are only used for StartImport calls that // are importing a password-protected repository. VCSUsername *string `json:"vcs_username,omitempty"` VCSPassword *string `json:"vcs_password,omitempty"` // For a tfvc import, the name of the project that is being imported. TFVCProject *string `json:"tfvc_project,omitempty"` // LFS related fields that may be preset in the Import Progress response // Describes whether the import has been opted in or out of using Git // LFS. The value can be 'opt_in', 'opt_out', or 'undecided' if no // action has been taken. UseLFS *string `json:"use_lfs,omitempty"` // Describes whether files larger than 100MB were found during the // importing step. HasLargeFiles *bool `json:"has_large_files,omitempty"` // The total size in gigabytes of files larger than 100MB found in the // originating repository. LargeFilesSize *int `json:"large_files_size,omitempty"` // The total number of files larger than 100MB found in the originating // repository. To see a list of these files, call LargeFiles. LargeFilesCount *int `json:"large_files_count,omitempty"` // Identifies the current status of an import. An import that does not // have errors will progress through these steps: // // detecting - the "detection" step of the import is in progress // because the request did not include a VCS parameter. The // import is identifying the type of source control present at // the URL. // importing - the "raw" step of the import is in progress. This is // where commit data is fetched from the original repository. // The import progress response will include CommitCount (the // total number of raw commits that will be imported) and // Percent (0 - 100, the current progress through the import). // mapping - the "rewrite" step of the import is in progress. This // is where SVN branches are converted to Git branches, and // where author updates are applied. The import progress // response does not include progress information. // pushing - the "push" step of the import is in progress. This is // where the importer updates the repository on GitHub. The // import progress response will include PushPercent, which is // the percent value reported by git push when it is "Writing // objects". // complete - the import is complete, and the repository is ready // on GitHub. // // If there are problems, you will see one of these in the status field: // // auth_failed - the import requires authentication in order to // connect to the original repository. Make an UpdateImport // request, and include VCSUsername and VCSPassword. // error - the import encountered an error. The import progress // response will include the FailedStep and an error message. // Contact GitHub support for more information. // detection_needs_auth - the importer requires authentication for // the originating repository to continue detection. Make an // UpdatImport request, and include VCSUsername and // VCSPassword. // detection_found_nothing - the importer didn't recognize any // source control at the URL. // detection_found_multiple - the importer found several projects // or repositories at the provided URL. When this is the case, // the Import Progress response will also include a // ProjectChoices field with the possible project choices as // values. Make an UpdateImport request, and include VCS and // (if applicable) TFVCProject. Status *string `json:"status,omitempty"` CommitCount *int `json:"commit_count,omitempty"` StatusText *string `json:"status_text,omitempty"` AuthorsCount *int `json:"authors_count,omitempty"` Percent *int `json:"percent,omitempty"` PushPercent *int `json:"push_percent,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` AuthorsURL *string `json:"authors_url,omitempty"` RepositoryURL *string `json:"repository_url,omitempty"` Message *string `json:"message,omitempty"` FailedStep *string `json:"failed_step,omitempty"` // Human readable display name, provided when the Import appears as // part of ProjectChoices. HumanName *string `json:"human_name,omitempty"` // When the importer finds several projects or repositories at the // provided URLs, this will identify the available choices. Call // UpdateImport with the selected Import value. ProjectChoices []Import `json:"project_choices,omitempty"` } func (i Import) String() string { return Stringify(i) } // SourceImportAuthor identifies an author imported from a source repository. // // GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-commit-authors type SourceImportAuthor struct { ID *int64 `json:"id,omitempty"` RemoteID *string `json:"remote_id,omitempty"` RemoteName *string `json:"remote_name,omitempty"` Email *string `json:"email,omitempty"` Name *string `json:"name,omitempty"` URL *string `json:"url,omitempty"` ImportURL *string `json:"import_url,omitempty"` } func (a SourceImportAuthor) String() string { return Stringify(a) } // LargeFile identifies a file larger than 100MB found during a repository import. // // GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-large-files type LargeFile struct { RefName *string `json:"ref_name,omitempty"` Path *string `json:"path,omitempty"` OID *string `json:"oid,omitempty"` Size *int `json:"size,omitempty"` } func (f LargeFile) String() string { return Stringify(f) } // StartImport initiates a repository import. // // GitHub API docs: https://developer.github.com/v3/migration/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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeImportPreview) out := new(Import) resp, err := s.client.Do(ctx, req, out) if err != nil { return nil, resp, err } return out, resp, nil } // 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 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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeImportPreview) out := new(Import) resp, err := s.client.Do(ctx, req, out) if err != nil { return nil, resp, err } return out, resp, nil } // UpdateImport initiates a repository import. // // GitHub API docs: https://developer.github.com/v3/migration/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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeImportPreview) out := new(Import) resp, err := s.client.Do(ctx, req, out) if err != nil { return nil, resp, err } return out, resp, nil } // CommitAuthors gets the authors mapped from the original repository. // // Each type of source control system represents authors in a different way. // For example, a Git commit author has a display name and an email address, // but a Subversion commit author just has a username. The GitHub Importer will // make the author information valid, but the author might not be correct. For // example, it will change the bare Subversion username "hubot" into something // like "hubot ". // // 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 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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeImportPreview) var authors []*SourceImportAuthor resp, err := s.client.Do(ctx, req, &authors) if err != nil { return nil, resp, err } return authors, resp, nil } // MapCommitAuthor updates an author's identity for the import. Your // 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 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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeImportPreview) out := new(SourceImportAuthor) resp, err := s.client.Do(ctx, req, out) if err != nil { return nil, resp, err } return out, resp, nil } // SetLFSPreference sets whether imported repositories should use Git LFS for // 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 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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeImportPreview) out := new(Import) resp, err := s.client.Do(ctx, req, out) if err != nil { return nil, resp, err } return out, resp, nil } // LargeFiles lists files larger than 100MB found during the import. // // GitHub API docs: https://developer.github.com/v3/migration/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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeImportPreview) var files []*LargeFile resp, err := s.client.Do(ctx, req, &files) if err != nil { return nil, resp, err } return files, resp, nil } // CancelImport stops an import for a repository. // // GitHub API docs: https://developer.github.com/v3/migration/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) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeImportPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/migrations_source_import_test.go000066400000000000000000000142741353501270500234770ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestMigrationService_StartImport(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Import{ VCS: String("git"), VCSURL: String("url"), VCSUsername: String("u"), VCSPassword: String("p"), } mux.HandleFunc("/repos/o/r/import", func(w http.ResponseWriter, r *http.Request) { v := new(Import) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeImportPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } w.WriteHeader(http.StatusCreated) fmt.Fprint(w, `{"status":"importing"}`) }) got, _, err := client.Migrations.StartImport(context.Background(), "o", "r", input) if err != nil { t.Errorf("StartImport returned error: %v", err) } want := &Import{Status: String("importing")} if !reflect.DeepEqual(got, want) { t.Errorf("StartImport = %+v, want %+v", got, want) } } func TestMigrationService_ImportProgress(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/import", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeImportPreview) fmt.Fprint(w, `{"status":"complete"}`) }) got, _, err := client.Migrations.ImportProgress(context.Background(), "o", "r") if err != nil { t.Errorf("ImportProgress returned error: %v", err) } want := &Import{Status: String("complete")} if !reflect.DeepEqual(got, want) { t.Errorf("ImportProgress = %+v, want %+v", got, want) } } func TestMigrationService_UpdateImport(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Import{ VCS: String("git"), VCSURL: String("url"), VCSUsername: String("u"), VCSPassword: String("p"), } mux.HandleFunc("/repos/o/r/import", func(w http.ResponseWriter, r *http.Request) { v := new(Import) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeImportPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } w.WriteHeader(http.StatusCreated) fmt.Fprint(w, `{"status":"importing"}`) }) got, _, err := client.Migrations.UpdateImport(context.Background(), "o", "r", input) if err != nil { t.Errorf("UpdateImport returned error: %v", err) } want := &Import{Status: String("importing")} if !reflect.DeepEqual(got, want) { t.Errorf("UpdateImport = %+v, want %+v", got, want) } } func TestMigrationService_CommitAuthors(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/import/authors", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeImportPreview) fmt.Fprint(w, `[{"id":1,"name":"a"},{"id":2,"name":"b"}]`) }) got, _, err := client.Migrations.CommitAuthors(context.Background(), "o", "r") if err != nil { t.Errorf("CommitAuthors returned error: %v", err) } want := []*SourceImportAuthor{ {ID: Int64(1), Name: String("a")}, {ID: Int64(2), Name: String("b")}, } if !reflect.DeepEqual(got, want) { t.Errorf("CommitAuthors = %+v, want %+v", got, want) } } func TestMigrationService_MapCommitAuthor(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &SourceImportAuthor{Name: String("n"), Email: String("e")} mux.HandleFunc("/repos/o/r/import/authors/1", func(w http.ResponseWriter, r *http.Request) { v := new(SourceImportAuthor) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeImportPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id": 1}`) }) got, _, err := client.Migrations.MapCommitAuthor(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("MapCommitAuthor returned error: %v", err) } want := &SourceImportAuthor{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("MapCommitAuthor = %+v, want %+v", got, want) } } func TestMigrationService_SetLFSPreference(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Import{UseLFS: String("opt_in")} mux.HandleFunc("/repos/o/r/import/lfs", func(w http.ResponseWriter, r *http.Request) { v := new(Import) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeImportPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } w.WriteHeader(http.StatusCreated) fmt.Fprint(w, `{"status":"importing"}`) }) got, _, err := client.Migrations.SetLFSPreference(context.Background(), "o", "r", input) if err != nil { t.Errorf("SetLFSPreference returned error: %v", err) } want := &Import{Status: String("importing")} if !reflect.DeepEqual(got, want) { t.Errorf("SetLFSPreference = %+v, want %+v", got, want) } } func TestMigrationService_LargeFiles(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/import/large_files", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeImportPreview) fmt.Fprint(w, `[{"oid":"a"},{"oid":"b"}]`) }) got, _, err := client.Migrations.LargeFiles(context.Background(), "o", "r") if err != nil { t.Errorf("LargeFiles returned error: %v", err) } want := []*LargeFile{ {OID: String("a")}, {OID: String("b")}, } if !reflect.DeepEqual(got, want) { t.Errorf("LargeFiles = %+v, want %+v", got, want) } } func TestMigrationService_CancelImport(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/import", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeImportPreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Migrations.CancelImport(context.Background(), "o", "r") if err != nil { t.Errorf("CancelImport returned error: %v", err) } } go-github-28.1.1/github/migrations_test.go000066400000000000000000000121071353501270500205160ustar00rootroot00000000000000// 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" "reflect" "strings" "testing" ) func TestMigrationService_StartMigration(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/migrations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) w.WriteHeader(http.StatusCreated) w.Write(migrationJSON) }) opt := &MigrationOptions{ LockRepositories: true, ExcludeAttachments: false, } got, _, err := client.Migrations.StartMigration(context.Background(), "o", []string{"r"}, opt) if err != nil { t.Errorf("StartMigration returned error: %v", err) } if want := wantMigration; !reflect.DeepEqual(got, want) { t.Errorf("StartMigration = %+v, want %+v", got, want) } } func TestMigrationService_ListMigrations(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/migrations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) w.WriteHeader(http.StatusOK) w.Write([]byte(fmt.Sprintf("[%s]", migrationJSON))) }) got, _, err := client.Migrations.ListMigrations(context.Background(), "o") if err != nil { t.Errorf("ListMigrations returned error: %v", err) } if want := []*Migration{wantMigration}; !reflect.DeepEqual(got, want) { t.Errorf("ListMigrations = %+v, want %+v", got, want) } } func TestMigrationService_MigrationStatus(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/migrations/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) w.WriteHeader(http.StatusOK) w.Write(migrationJSON) }) got, _, err := client.Migrations.MigrationStatus(context.Background(), "o", 1) if err != nil { t.Errorf("MigrationStatus returned error: %v", err) } if want := wantMigration; !reflect.DeepEqual(got, want) { t.Errorf("MigrationStatus = %+v, want %+v", got, want) } } func TestMigrationService_MigrationArchiveURL(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/migrations/1/archive", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) http.Redirect(w, r, "/yo", http.StatusFound) }) mux.HandleFunc("/yo", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusOK) w.Write([]byte("0123456789abcdef")) }) got, err := client.Migrations.MigrationArchiveURL(context.Background(), "o", 1) if err != nil { t.Errorf("MigrationStatus returned error: %v", err) } if want := "/yo"; !strings.HasSuffix(got, want) { t.Errorf("MigrationArchiveURL = %+v, want %+v", got, want) } } func TestMigrationService_DeleteMigration(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/migrations/1/archive", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) w.WriteHeader(http.StatusNoContent) }) if _, err := client.Migrations.DeleteMigration(context.Background(), "o", 1); err != nil { t.Errorf("DeleteMigration returned error: %v", err) } } func TestMigrationService_UnlockRepo(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/migrations/1/repos/r/lock", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) w.WriteHeader(http.StatusNoContent) }) if _, err := client.Migrations.UnlockRepo(context.Background(), "o", 1, "r"); err != nil { t.Errorf("UnlockRepo returned error: %v", err) } } var migrationJSON = []byte(`{ "id": 79, "guid": "0b989ba4-242f-11e5-81e1-c7b6966d2516", "state": "pending", "lock_repositories": true, "exclude_attachments": false, "url": "https://api.github.com/orgs/octo-org/migrations/79", "created_at": "2015-07-06T15:33:38-07:00", "updated_at": "2015-07-06T15:33:38-07:00", "repositories": [ { "id": 1296269, "name": "Hello-World", "full_name": "octocat/Hello-World", "description": "This your first repo!" } ] }`) var wantMigration = &Migration{ ID: Int64(79), GUID: String("0b989ba4-242f-11e5-81e1-c7b6966d2516"), State: String("pending"), LockRepositories: Bool(true), ExcludeAttachments: Bool(false), URL: String("https://api.github.com/orgs/octo-org/migrations/79"), CreatedAt: String("2015-07-06T15:33:38-07:00"), UpdatedAt: String("2015-07-06T15:33:38-07:00"), Repositories: []*Repository{ { ID: Int64(1296269), Name: String("Hello-World"), FullName: String("octocat/Hello-World"), Description: String("This your first repo!"), }, }, } go-github-28.1.1/github/migrations_user.go000066400000000000000000000160071353501270500205200ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "errors" "fmt" "net/http" ) // UserMigration represents a GitHub migration (archival). type UserMigration struct { ID *int64 `json:"id,omitempty"` GUID *string `json:"guid,omitempty"` // State is the current state of a migration. // Possible values are: // "pending" which means the migration hasn't started yet, // "exporting" which means the migration is in progress, // "exported" which means the migration finished successfully, or // "failed" which means the migration failed. State *string `json:"state,omitempty"` // LockRepositories indicates whether repositories are locked (to prevent // manipulation) while migrating data. LockRepositories *bool `json:"lock_repositories,omitempty"` // ExcludeAttachments indicates whether attachments should be excluded from // the migration (to reduce migration archive file size). ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` URL *string `json:"url,omitempty"` CreatedAt *string `json:"created_at,omitempty"` UpdatedAt *string `json:"updated_at,omitempty"` Repositories []*Repository `json:"repositories,omitempty"` } func (m UserMigration) String() string { return Stringify(m) } // UserMigrationOptions specifies the optional parameters to Migration methods. type UserMigrationOptions struct { // LockRepositories indicates whether repositories should be locked (to prevent // manipulation) while migrating data. LockRepositories bool // ExcludeAttachments indicates whether attachments should be excluded from // the migration (to reduce migration archive file size). ExcludeAttachments bool } // startUserMigration represents the body of a StartMigration request. type startUserMigration struct { // Repositories is a slice of repository names to migrate. Repositories []string `json:"repositories,omitempty"` // LockRepositories indicates whether repositories should be locked (to prevent // manipulation) while migrating data. LockRepositories *bool `json:"lock_repositories,omitempty"` // ExcludeAttachments indicates whether attachments should be excluded from // the migration (to reduce migration archive file size). ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` } // StartUserMigration starts the generation of a migration archive. // repos is a slice of repository names to migrate. // // GitHub API docs: https://developer.github.com/v3/migrations/users/#start-a-user-migration func (s *MigrationService) StartUserMigration(ctx context.Context, repos []string, opt *UserMigrationOptions) (*UserMigration, *Response, error) { u := "user/migrations" body := &startUserMigration{Repositories: repos} if opt != nil { body.LockRepositories = Bool(opt.LockRepositories) body.ExcludeAttachments = Bool(opt.ExcludeAttachments) } req, err := s.client.NewRequest("POST", u, body) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) m := &UserMigration{} resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } // ListUserMigrations lists the most recent migrations. // // GitHub API docs: https://developer.github.com/v3/migrations/users/#get-a-list-of-user-migrations func (s *MigrationService) ListUserMigrations(ctx context.Context) ([]*UserMigration, *Response, error) { u := "user/migrations" req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) var m []*UserMigration resp, err := s.client.Do(ctx, req, &m) if err != nil { return nil, resp, err } return m, resp, nil } // UserMigrationStatus gets the status of a specific migration archive. // id is the migration ID. // // GitHub API docs: https://developer.github.com/v3/migrations/users/#get-the-status-of-a-user-migration func (s *MigrationService) UserMigrationStatus(ctx context.Context, id int64) (*UserMigration, *Response, error) { u := fmt.Sprintf("user/migrations/%v", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) m := &UserMigration{} resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } // UserMigrationArchiveURL gets the URL for a specific migration archive. // id is the migration ID. // // GitHub API docs: https://developer.github.com/v3/migrations/users/#download-a-user-migration-archive func (s *MigrationService) UserMigrationArchiveURL(ctx context.Context, id int64) (string, error) { url := fmt.Sprintf("user/migrations/%v/archive", id) req, err := s.client.NewRequest("GET", url, nil) if err != nil { return "", err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) m := &UserMigration{} var loc string originalRedirect := s.client.client.CheckRedirect s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { loc = req.URL.String() return http.ErrUseLastResponse } defer func() { s.client.client.CheckRedirect = originalRedirect }() resp, err := s.client.Do(ctx, req, m) if err == nil { return "", errors.New("expected redirect, none provided") } loc = resp.Header.Get("Location") return loc, nil } // DeleteUserMigration will delete a previous migration archive. // id is the migration ID. // // GitHub API docs: https://developer.github.com/v3/migrations/users/#delete-a-user-migration-archive func (s *MigrationService) DeleteUserMigration(ctx context.Context, id int64) (*Response, error) { url := fmt.Sprintf("user/migrations/%v/archive", id) req, err := s.client.NewRequest("DELETE", url, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) return s.client.Do(ctx, req, nil) } // UnlockUserRepo will unlock a repo that was locked for migration. // id is migration ID. // 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/migrations/users/#unlock-a-user-repository func (s *MigrationService) UnlockUserRepo(ctx context.Context, id int64, repo string) (*Response, error) { url := fmt.Sprintf("user/migrations/%v/repos/%v/lock", id, repo) req, err := s.client.NewRequest("DELETE", url, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMigrationsPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/migrations_user_test.go000066400000000000000000000127061353501270500215610ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "net/http" "reflect" "strings" "testing" ) func TestMigrationService_StartUserMigration(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/migrations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) w.WriteHeader(http.StatusCreated) w.Write(userMigrationJSON) }) opt := &UserMigrationOptions{ LockRepositories: true, ExcludeAttachments: false, } got, _, err := client.Migrations.StartUserMigration(context.Background(), []string{"r"}, opt) if err != nil { t.Errorf("StartUserMigration returned error: %v", err) } want := wantUserMigration if !reflect.DeepEqual(want, got) { t.Errorf("StartUserMigration = %v, want = %v", got, want) } } func TestMigrationService_ListUserMigrations(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/migrations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) w.WriteHeader(http.StatusOK) w.Write([]byte(fmt.Sprintf("[%s]", userMigrationJSON))) }) got, _, err := client.Migrations.ListUserMigrations(context.Background()) if err != nil { t.Errorf("ListUserMigrations returned error %v", err) } want := []*UserMigration{wantUserMigration} if !reflect.DeepEqual(want, got) { t.Errorf("ListUserMigrations = %v, want = %v", got, want) } } func TestMigrationService_UserMigrationStatus(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/migrations/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) w.WriteHeader(http.StatusOK) w.Write(userMigrationJSON) }) got, _, err := client.Migrations.UserMigrationStatus(context.Background(), 1) if err != nil { t.Errorf("UserMigrationStatus returned error %v", err) } want := wantUserMigration if !reflect.DeepEqual(want, got) { t.Errorf("UserMigrationStatus = %v, want = %v", got, want) } } func TestMigrationService_UserMigrationArchiveURL(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/migrations/1/archive", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) http.Redirect(w, r, "/go-github", http.StatusFound) }) mux.HandleFunc("/go-github", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusOK) }) got, err := client.Migrations.UserMigrationArchiveURL(context.Background(), 1) if err != nil { t.Errorf("UserMigrationArchiveURL returned error %v", err) } want := "/go-github" if !strings.HasSuffix(got, want) { t.Errorf("UserMigrationArchiveURL = %v, want = %v", got, want) } } func TestMigrationService_DeleteUserMigration(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/migrations/1/archive", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) w.WriteHeader(http.StatusNoContent) }) got, err := client.Migrations.DeleteUserMigration(context.Background(), 1) if err != nil { t.Errorf("DeleteUserMigration returned error %v", err) } if got.StatusCode != http.StatusNoContent { t.Errorf("DeleteUserMigration returned status = %v, want = %v", got.StatusCode, http.StatusNoContent) } } func TestMigrationService_UnlockUserRepo(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/migrations/1/repos/r/lock", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeMigrationsPreview) w.WriteHeader(http.StatusNoContent) }) got, err := client.Migrations.UnlockUserRepo(context.Background(), 1, "r") if err != nil { t.Errorf("UnlockUserRepo returned error %v", err) } if got.StatusCode != http.StatusNoContent { t.Errorf("UnlockUserRepo returned status = %v, want = %v", got.StatusCode, http.StatusNoContent) } } var userMigrationJSON = []byte(`{ "id": 79, "guid": "0b989ba4-242f-11e5-81e1-c7b6966d2516", "state": "pending", "lock_repositories": true, "exclude_attachments": false, "url": "https://api.github.com/orgs/octo-org/migrations/79", "created_at": "2015-07-06T15:33:38-07:00", "updated_at": "2015-07-06T15:33:38-07:00", "repositories": [ { "id": 1296269, "name": "Hello-World", "full_name": "octocat/Hello-World", "description": "This your first repo!" } ] }`) var wantUserMigration = &UserMigration{ ID: Int64(79), GUID: String("0b989ba4-242f-11e5-81e1-c7b6966d2516"), State: String("pending"), LockRepositories: Bool(true), ExcludeAttachments: Bool(false), URL: String("https://api.github.com/orgs/octo-org/migrations/79"), CreatedAt: String("2015-07-06T15:33:38-07:00"), UpdatedAt: String("2015-07-06T15:33:38-07:00"), Repositories: []*Repository{ { ID: Int64(1296269), Name: String("Hello-World"), FullName: String("octocat/Hello-World"), Description: String("This your first repo!"), }, }, } go-github-28.1.1/github/misc.go000066400000000000000000000160741353501270500162450ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "bytes" "context" "fmt" "net/url" ) // MarkdownOptions specifies optional parameters to the Markdown method. type MarkdownOptions struct { // Mode identifies the rendering mode. Possible values are: // markdown - render a document as plain Markdown, just like // README files are rendered. // // gfm - to render a document as user-content, e.g. like user // comments or issues are rendered. In GFM mode, hard line breaks are // always taken into account, and issue and user mentions are linked // accordingly. // // Default is "markdown". Mode string // Context identifies the repository context. Only taken into account // when rendering as "gfm". Context string } type markdownRequest struct { Text *string `json:"text,omitempty"` Mode *string `json:"mode,omitempty"` Context *string `json:"context,omitempty"` } // Markdown renders an arbitrary Markdown document. // // GitHub API docs: https://developer.github.com/v3/markdown/ func (c *Client) Markdown(ctx context.Context, text string, opt *MarkdownOptions) (string, *Response, error) { request := &markdownRequest{Text: String(text)} if opt != nil { if opt.Mode != "" { request.Mode = String(opt.Mode) } if opt.Context != "" { request.Context = String(opt.Context) } } req, err := c.NewRequest("POST", "markdown", request) if err != nil { return "", nil, err } buf := new(bytes.Buffer) resp, err := c.Do(ctx, req, buf) if err != nil { return "", resp, err } return buf.String(), resp, nil } // ListEmojis returns the emojis available to use on GitHub. // // GitHub API docs: https://developer.github.com/v3/emojis/ func (c *Client) ListEmojis(ctx context.Context) (map[string]string, *Response, error) { req, err := c.NewRequest("GET", "emojis", nil) if err != nil { return nil, nil, err } var emoji map[string]string resp, err := c.Do(ctx, req, &emoji) if err != nil { return nil, resp, err } return emoji, resp, nil } // CodeOfConduct represents a code of conduct. type CodeOfConduct struct { Name *string `json:"name,omitempty"` Key *string `json:"key,omitempty"` URL *string `json:"url,omitempty"` Body *string `json:"body,omitempty"` } func (c *CodeOfConduct) String() string { return Stringify(c) } // ListCodesOfConduct returns all codes of conduct. // // GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#list-all-codes-of-conduct func (c *Client) ListCodesOfConduct(ctx context.Context) ([]*CodeOfConduct, *Response, error) { req, err := c.NewRequest("GET", "codes_of_conduct", nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeCodesOfConductPreview) var cs []*CodeOfConduct resp, err := c.Do(ctx, req, &cs) if err != nil { return nil, resp, err } return cs, resp, nil } // GetCodeOfConduct returns an individual code of conduct. // // https://developer.github.com/v3/codes_of_conduct/#get-an-individual-code-of-conduct func (c *Client) GetCodeOfConduct(ctx context.Context, key string) (*CodeOfConduct, *Response, error) { u := fmt.Sprintf("codes_of_conduct/%s", key) req, err := c.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeCodesOfConductPreview) coc := new(CodeOfConduct) resp, err := c.Do(ctx, req, coc) if err != nil { return nil, resp, err } return coc, resp, nil } // APIMeta represents metadata about the GitHub API. type APIMeta struct { // An Array of IP addresses in CIDR format specifying the addresses // that incoming service hooks will originate from on GitHub.com. Hooks []string `json:"hooks,omitempty"` // An Array of IP addresses in CIDR format specifying the Git servers // for GitHub.com. Git []string `json:"git,omitempty"` // Whether authentication with username and password is supported. // (GitHub Enterprise instances using CAS or OAuth for authentication // will return false. Features like Basic Authentication with a // username and password, sudo mode, and two-factor authentication are // not supported on these servers.) VerifiablePasswordAuthentication *bool `json:"verifiable_password_authentication,omitempty"` // An array of IP addresses in CIDR format specifying the addresses // which serve GitHub Pages websites. Pages []string `json:"pages,omitempty"` // An Array of IP addresses specifying the addresses that source imports // will originate from on GitHub.com. Importer []string `json:"importer,omitempty"` } // APIMeta returns information about GitHub.com, the service. Or, if you access // this endpoint on your organization’s GitHub Enterprise installation, this // endpoint provides information about that installation. // // GitHub API docs: https://developer.github.com/v3/meta/ func (c *Client) APIMeta(ctx context.Context) (*APIMeta, *Response, error) { req, err := c.NewRequest("GET", "meta", nil) if err != nil { return nil, nil, err } meta := new(APIMeta) resp, err := c.Do(ctx, req, meta) if err != nil { return nil, resp, err } return meta, resp, nil } // Octocat returns an ASCII art octocat with the specified message in a speech // bubble. If message is empty, a random zen phrase is used. func (c *Client) Octocat(ctx context.Context, message string) (string, *Response, error) { u := "octocat" if message != "" { u = fmt.Sprintf("%s?s=%s", u, url.QueryEscape(message)) } req, err := c.NewRequest("GET", u, nil) if err != nil { return "", nil, err } buf := new(bytes.Buffer) resp, err := c.Do(ctx, req, buf) if err != nil { return "", resp, err } return buf.String(), resp, nil } // Zen returns a random line from The Zen of GitHub. // // see also: http://warpspire.com/posts/taste/ func (c *Client) Zen(ctx context.Context) (string, *Response, error) { req, err := c.NewRequest("GET", "zen", nil) if err != nil { return "", nil, err } buf := new(bytes.Buffer) resp, err := c.Do(ctx, req, buf) if err != nil { return "", resp, err } return buf.String(), resp, nil } // ServiceHook represents a hook that has configuration settings, a list of // available events, and default events. type ServiceHook struct { Name *string `json:"name,omitempty"` Events []string `json:"events,omitempty"` SupportedEvents []string `json:"supported_events,omitempty"` Schema [][]string `json:"schema,omitempty"` } func (s *ServiceHook) String() string { return Stringify(s) } // ListServiceHooks lists all of the available service hooks. // // GitHub API docs: https://developer.github.com/webhooks/#services func (c *Client) ListServiceHooks(ctx context.Context) ([]*ServiceHook, *Response, error) { u := "hooks" req, err := c.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var hooks []*ServiceHook resp, err := c.Do(ctx, req, &hooks) if err != nil { return nil, resp, err } return hooks, resp, nil } go-github-28.1.1/github/misc_test.go000066400000000000000000000130231353501270500172730ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestMarkdown(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &markdownRequest{ Text: String("# text #"), Mode: String("gfm"), Context: String("google/go-github"), } mux.HandleFunc("/markdown", func(w http.ResponseWriter, r *http.Request) { v := new(markdownRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `

text

`) }) md, _, err := client.Markdown(context.Background(), "# text #", &MarkdownOptions{ Mode: "gfm", Context: "google/go-github", }) if err != nil { t.Errorf("Markdown returned error: %v", err) } if want := "

text

"; want != md { t.Errorf("Markdown returned %+v, want %+v", md, want) } } func TestListEmojis(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/emojis", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"+1": "+1.png"}`) }) emoji, _, err := client.ListEmojis(context.Background()) if err != nil { t.Errorf("ListEmojis returned error: %v", err) } want := map[string]string{"+1": "+1.png"} if !reflect.DeepEqual(want, emoji) { t.Errorf("ListEmojis returned %+v, want %+v", emoji, want) } } func TestListCodesOfConduct(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/codes_of_conduct", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeCodesOfConductPreview) fmt.Fprint(w, `[{ "key": "key", "name": "name", "url": "url"} ]`) }) cs, _, err := client.ListCodesOfConduct(context.Background()) if err != nil { t.Errorf("ListCodesOfConduct returned error: %v", err) } want := []*CodeOfConduct{ { Key: String("key"), Name: String("name"), URL: String("url"), }} if !reflect.DeepEqual(want, cs) { t.Errorf("ListCodesOfConduct returned %+v, want %+v", cs, want) } } func TestGetCodeOfConduct(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/codes_of_conduct/k", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeCodesOfConductPreview) fmt.Fprint(w, `{ "key": "key", "name": "name", "url": "url", "body": "body"}`, ) }) coc, _, err := client.GetCodeOfConduct(context.Background(), "k") if err != nil { t.Errorf("ListCodesOfConduct returned error: %v", err) } want := &CodeOfConduct{ Key: String("key"), Name: String("name"), URL: String("url"), Body: String("body"), } if !reflect.DeepEqual(want, coc) { t.Errorf("GetCodeOfConductByKey returned %+v, want %+v", coc, want) } } func TestAPIMeta(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/meta", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"hooks":["h"], "git":["g"], "pages":["p"], "importer":["i"], "verifiable_password_authentication": true}`) }) meta, _, err := client.APIMeta(context.Background()) if err != nil { t.Errorf("APIMeta returned error: %v", err) } want := &APIMeta{ Hooks: []string{"h"}, Git: []string{"g"}, Pages: []string{"p"}, Importer: []string{"i"}, VerifiablePasswordAuthentication: Bool(true), } if !reflect.DeepEqual(want, meta) { t.Errorf("APIMeta returned %+v, want %+v", meta, want) } } func TestOctocat(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := "input" output := "sample text" mux.HandleFunc("/octocat", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"s": input}) w.Header().Set("Content-Type", "application/octocat-stream") fmt.Fprint(w, output) }) got, _, err := client.Octocat(context.Background(), input) if err != nil { t.Errorf("Octocat returned error: %v", err) } if want := output; got != want { t.Errorf("Octocat returned %+v, want %+v", got, want) } } func TestZen(t *testing.T) { client, mux, _, teardown := setup() defer teardown() output := "sample text" mux.HandleFunc("/zen", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.Header().Set("Content-Type", "text/plain;charset=utf-8") fmt.Fprint(w, output) }) got, _, err := client.Zen(context.Background()) if err != nil { t.Errorf("Zen returned error: %v", err) } if want := output; got != want { t.Errorf("Zen returned %+v, want %+v", got, want) } } func TestListServiceHooks(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/hooks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{ "name":"n", "events":["e"], "supported_events":["s"], "schema":[ ["a", "b"] ] }]`) }) hooks, _, err := client.ListServiceHooks(context.Background()) if err != nil { t.Errorf("ListServiceHooks returned error: %v", err) } want := []*ServiceHook{{ Name: String("n"), Events: []string{"e"}, SupportedEvents: []string{"s"}, Schema: [][]string{{"a", "b"}}, }} if !reflect.DeepEqual(hooks, want) { t.Errorf("ListServiceHooks returned %+v, want %+v", hooks, want) } } go-github-28.1.1/github/orgs.go000066400000000000000000000171151353501270500162610ustar00rootroot00000000000000// 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" "time" ) // OrganizationsService provides access to the organization related functions // in the GitHub API. // // GitHub API docs: https://developer.github.com/v3/orgs/ type OrganizationsService service // Organization represents a GitHub organization account. type Organization struct { Login *string `json:"login,omitempty"` ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` AvatarURL *string `json:"avatar_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` Name *string `json:"name,omitempty"` Company *string `json:"company,omitempty"` Blog *string `json:"blog,omitempty"` Location *string `json:"location,omitempty"` Email *string `json:"email,omitempty"` Description *string `json:"description,omitempty"` PublicRepos *int `json:"public_repos,omitempty"` PublicGists *int `json:"public_gists,omitempty"` Followers *int `json:"followers,omitempty"` Following *int `json:"following,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` TotalPrivateRepos *int `json:"total_private_repos,omitempty"` OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"` PrivateGists *int `json:"private_gists,omitempty"` DiskUsage *int `json:"disk_usage,omitempty"` Collaborators *int `json:"collaborators,omitempty"` BillingEmail *string `json:"billing_email,omitempty"` Type *string `json:"type,omitempty"` Plan *Plan `json:"plan,omitempty"` TwoFactorRequirementEnabled *bool `json:"two_factor_requirement_enabled,omitempty"` // DefaultRepoPermission can be one of: "read", "write", "admin", or "none". (Default: "read"). // It is only used in OrganizationsService.Edit. DefaultRepoPermission *string `json:"default_repository_permission,omitempty"` // DefaultRepoSettings can be one of: "read", "write", "admin", or "none". (Default: "read"). // It is only used in OrganizationsService.Get. DefaultRepoSettings *string `json:"default_repository_settings,omitempty"` // MembersCanCreateRepos default value is true and is only used in Organizations.Edit. MembersCanCreateRepos *bool `json:"members_can_create_repositories,omitempty"` // MembersAllowedRepositoryCreationType denotes if organization members can create repositories // and the type of repositories they can create. Possible values are: "all", "private", or "none". MembersAllowedRepositoryCreationType *string `json:"members_allowed_repository_creation_type,omitempty"` // API URLs URL *string `json:"url,omitempty"` EventsURL *string `json:"events_url,omitempty"` HooksURL *string `json:"hooks_url,omitempty"` IssuesURL *string `json:"issues_url,omitempty"` MembersURL *string `json:"members_url,omitempty"` PublicMembersURL *string `json:"public_members_url,omitempty"` ReposURL *string `json:"repos_url,omitempty"` } func (o Organization) String() string { return Stringify(o) } // Plan represents the payment plan for an account. See plans at https://github.com/plans. type Plan struct { Name *string `json:"name,omitempty"` Space *int `json:"space,omitempty"` Collaborators *int `json:"collaborators,omitempty"` PrivateRepos *int `json:"private_repos,omitempty"` } func (p Plan) String() string { return Stringify(p) } // OrganizationsListOptions specifies the optional parameters to the // OrganizationsService.ListAll method. type OrganizationsListOptions struct { // Since filters Organizations by ID. Since int64 `url:"since,omitempty"` // Note: Pagination is powered exclusively by the Since parameter, // ListOptions.Page has no effect. // ListOptions.PerPage controls an undocumented GitHub API parameter. ListOptions } // ListAll lists all organizations, in the order that they were created on GitHub. // // Note: Pagination is powered exclusively by the since parameter. To continue // listing the next set of organizations, use the ID of the last-returned organization // as the opts.Since parameter for the next call. // // GitHub API docs: https://developer.github.com/v3/orgs/#list-all-organizations func (s *OrganizationsService) ListAll(ctx context.Context, opt *OrganizationsListOptions) ([]*Organization, *Response, error) { u, err := addOptions("organizations", opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } orgs := []*Organization{} resp, err := s.client.Do(ctx, req, &orgs) if err != nil { return nil, resp, err } return orgs, resp, nil } // 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 func (s *OrganizationsService) List(ctx context.Context, user string, opt *ListOptions) ([]*Organization, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/orgs", user) } else { u = "user/orgs" } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var orgs []*Organization resp, err := s.client.Do(ctx, req, &orgs) if err != nil { return nil, resp, err } return orgs, resp, nil } // Get fetches an organization by name. // // GitHub API docs: https://developer.github.com/v3/orgs/#get-an-organization func (s *OrganizationsService) Get(ctx context.Context, org string) (*Organization, *Response, error) { u := fmt.Sprintf("orgs/%v", org) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview) organization := new(Organization) resp, err := s.client.Do(ctx, req, organization) if err != nil { return nil, resp, err } return organization, resp, nil } // GetByID fetches an organization. // // Note: GetByID uses the undocumented GitHub API endpoint /organizations/:id. func (s *OrganizationsService) GetByID(ctx context.Context, id int64) (*Organization, *Response, error) { u := fmt.Sprintf("organizations/%d", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } organization := new(Organization) resp, err := s.client.Do(ctx, req, organization) if err != nil { return nil, resp, err } return organization, resp, nil } // Edit an organization. // // GitHub API docs: https://developer.github.com/v3/orgs/#edit-an-organization 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) if err != nil { return nil, nil, err } o := new(Organization) resp, err := s.client.Do(ctx, req, o) if err != nil { return nil, resp, err } return o, resp, nil } go-github-28.1.1/github/orgs_hooks.go000066400000000000000000000063611353501270500174650ustar00rootroot00000000000000// Copyright 2015 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" ) // ListHooks lists all Hooks for the specified organization. // // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#list-hooks func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opt *ListOptions) ([]*Hook, *Response, error) { u := fmt.Sprintf("orgs/%v/hooks", org) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var hooks []*Hook resp, err := s.client.Do(ctx, req, &hooks) if err != nil { return nil, resp, err } return hooks, resp, nil } // GetHook returns a single specified Hook. // // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#get-single-hook func (s *OrganizationsService) GetHook(ctx context.Context, org string, id int64) (*Hook, *Response, error) { u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } hook := new(Hook) resp, err := s.client.Do(ctx, req, hook) return hook, resp, err } // CreateHook creates a Hook for the specified org. // Config is a required field. // // Note that only a subset of the hook fields are used and hook must // not be nil. // // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#create-a-hook func (s *OrganizationsService) CreateHook(ctx context.Context, org string, hook *Hook) (*Hook, *Response, error) { u := fmt.Sprintf("orgs/%v/hooks", org) hookReq := &createHookRequest{ Name: "web", Events: hook.Events, Active: hook.Active, Config: hook.Config, } req, err := s.client.NewRequest("POST", u, hookReq) if err != nil { return nil, nil, err } h := new(Hook) resp, err := s.client.Do(ctx, req, h) if err != nil { return nil, resp, err } return h, resp, nil } // EditHook updates a specified Hook. // // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#edit-a-hook func (s *OrganizationsService) EditHook(ctx context.Context, org string, id int64, hook *Hook) (*Hook, *Response, error) { u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) req, err := s.client.NewRequest("PATCH", u, hook) if err != nil { return nil, nil, err } h := new(Hook) resp, err := s.client.Do(ctx, req, h) return h, resp, err } // PingHook triggers a 'ping' event to be sent to the Hook. // // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#ping-a-hook func (s *OrganizationsService) PingHook(ctx context.Context, org string, id int64) (*Response, error) { u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // DeleteHook deletes a specified Hook. // // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#delete-a-hook func (s *OrganizationsService) DeleteHook(ctx context.Context, org string, id int64) (*Response, error) { u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/orgs_hooks_test.go000066400000000000000000000111441353501270500205170ustar00rootroot00000000000000// Copyright 2015 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestOrganizationsService_ListHooks(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/hooks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}, {"id":2}]`) }) opt := &ListOptions{Page: 2} hooks, _, err := client.Organizations.ListHooks(context.Background(), "o", opt) if err != nil { t.Errorf("Organizations.ListHooks returned error: %v", err) } want := []*Hook{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(hooks, want) { t.Errorf("Organizations.ListHooks returned %+v, want %+v", hooks, want) } } func TestOrganizationsService_ListHooks_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Organizations.ListHooks(context.Background(), "%", nil) testURLParseError(t, err) } func TestOrganizationsService_CreateHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Hook{CreatedAt: &referenceTime} mux.HandleFunc("/orgs/o/hooks", func(w http.ResponseWriter, r *http.Request) { v := new(createHookRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := &createHookRequest{Name: "web"} if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"id":1}`) }) hook, _, err := client.Organizations.CreateHook(context.Background(), "o", input) if err != nil { t.Errorf("Organizations.CreateHook returned error: %v", err) } want := &Hook{ID: Int64(1)} if !reflect.DeepEqual(hook, want) { t.Errorf("Organizations.CreateHook returned %+v, want %+v", hook, want) } } func TestOrganizationsService_GetHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/hooks/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) hook, _, err := client.Organizations.GetHook(context.Background(), "o", 1) if err != nil { t.Errorf("Organizations.GetHook returned error: %v", err) } want := &Hook{ID: Int64(1)} if !reflect.DeepEqual(hook, want) { t.Errorf("Organizations.GetHook returned %+v, want %+v", hook, want) } } func TestOrganizationsService_GetHook_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Organizations.GetHook(context.Background(), "%", 1) testURLParseError(t, err) } func TestOrganizationsService_EditHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Hook{} mux.HandleFunc("/orgs/o/hooks/1", func(w http.ResponseWriter, r *http.Request) { v := new(Hook) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) hook, _, err := client.Organizations.EditHook(context.Background(), "o", 1, input) if err != nil { t.Errorf("Organizations.EditHook returned error: %v", err) } want := &Hook{ID: Int64(1)} if !reflect.DeepEqual(hook, want) { t.Errorf("Organizations.EditHook returned %+v, want %+v", hook, want) } } func TestOrganizationsService_EditHook_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Organizations.EditHook(context.Background(), "%", 1, nil) testURLParseError(t, err) } func TestOrganizationsService_PingHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/hooks/1/pings", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") }) _, err := client.Organizations.PingHook(context.Background(), "o", 1) if err != nil { t.Errorf("Organizations.PingHook returned error: %v", err) } } func TestOrganizationsService_DeleteHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/hooks/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Organizations.DeleteHook(context.Background(), "o", 1) if err != nil { t.Errorf("Organizations.DeleteHook returned error: %v", err) } } func TestOrganizationsService_DeleteHook_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Organizations.DeleteHook(context.Background(), "%", 1) testURLParseError(t, err) } go-github-28.1.1/github/orgs_members.go000066400000000000000000000303751353501270500177760ustar00rootroot00000000000000// 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" ) // Membership represents the status of a user's membership in an organization or team. type Membership struct { URL *string `json:"url,omitempty"` // State is the user's status within the organization or team. // Possible values are: "active", "pending" State *string `json:"state,omitempty"` // Role identifies the user's role within the organization or team. // Possible values for organization membership: // member - non-owner organization member // admin - organization owner // // Possible values for team membership are: // member - a normal member of the team // maintainer - a team maintainer. Able to add/remove other team // members, promote other team members to team // maintainer, and edit the team’s name and description Role *string `json:"role,omitempty"` // For organization membership, the API URL of the organization. OrganizationURL *string `json:"organization_url,omitempty"` // For organization membership, the organization the membership is for. Organization *Organization `json:"organization,omitempty"` // For organization membership, the user the membership is for. User *User `json:"user,omitempty"` } func (m Membership) String() string { return Stringify(m) } // ListMembersOptions specifies optional parameters to the // OrganizationsService.ListMembers method. type ListMembersOptions struct { // If true (or if the authenticated user is not an owner of the // organization), list only publicly visible members. PublicOnly bool `url:"-"` // Filter members returned in the list. Possible values are: // 2fa_disabled, all. Default is "all". Filter string `url:"filter,omitempty"` // Role filters members returned by their role in the organization. // Possible values are: // all - all members of the organization, regardless of role // admin - organization owners // member - non-owner organization members // // Default is "all". Role string `url:"role,omitempty"` ListOptions } // ListMembers lists the members for an organization. If the authenticated // 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 func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opt *ListMembersOptions) ([]*User, *Response, error) { var u string if opt != nil && opt.PublicOnly { u = fmt.Sprintf("orgs/%v/public_members", org) } else { u = fmt.Sprintf("orgs/%v/members", org) } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var members []*User resp, err := s.client.Do(ctx, req, &members) if err != nil { return nil, resp, err } return members, resp, nil } // IsMember checks if a user is a member of an organization. // // GitHub API docs: https://developer.github.com/v3/orgs/members/#check-membership func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) (bool, *Response, error) { u := fmt.Sprintf("orgs/%v/members/%v", org, user) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } resp, err := s.client.Do(ctx, req, nil) member, err := parseBoolResponse(err) return member, resp, err } // IsPublicMember checks if a user is a public member of an organization. // // GitHub API docs: https://developer.github.com/v3/orgs/members/#check-public-membership func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user string) (bool, *Response, error) { u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } resp, err := s.client.Do(ctx, req, nil) member, err := parseBoolResponse(err) return member, resp, err } // RemoveMember removes a user from all teams of an organization. // // GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-a-member func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/members/%v", org, user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // PublicizeMembership publicizes a user's membership in an organization. (A // user cannot publicize the membership for another user.) // // GitHub API docs: https://developer.github.com/v3/orgs/members/#publicize-a-users-membership func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // ConcealMembership conceals a user's membership in an organization. // // GitHub API docs: https://developer.github.com/v3/orgs/members/#conceal-a-users-membership func (s *OrganizationsService) ConcealMembership(ctx context.Context, org, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // ListOrgMembershipsOptions specifies optional parameters to the // OrganizationsService.ListOrgMemberships method. type ListOrgMembershipsOptions struct { // Filter memberships to include only those with the specified state. // Possible values are: "active", "pending". State string `url:"state,omitempty"` ListOptions } // ListOrgMemberships lists the organization memberships for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/orgs/members/#list-your-organization-memberships func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opt *ListOrgMembershipsOptions) ([]*Membership, *Response, error) { u := "user/memberships/orgs" u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var memberships []*Membership resp, err := s.client.Do(ctx, req, &memberships) if err != nil { return nil, resp, err } return memberships, resp, nil } // GetOrgMembership gets the membership for a user in a specified organization. // 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 func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org string) (*Membership, *Response, error) { var u string if user != "" { u = fmt.Sprintf("orgs/%v/memberships/%v", org, user) } else { u = fmt.Sprintf("user/memberships/orgs/%v", org) } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } membership := new(Membership) resp, err := s.client.Do(ctx, req, membership) if err != nil { return nil, resp, err } return membership, resp, nil } // EditOrgMembership edits the membership for user in specified organization. // Passing an empty string for user will edit the membership for the // authenticated user. // // GitHub API docs: https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership // GitHub API docs: https://developer.github.com/v3/orgs/members/#edit-your-organization-membership func (s *OrganizationsService) EditOrgMembership(ctx context.Context, user, org string, membership *Membership) (*Membership, *Response, error) { var u, method string if user != "" { u = fmt.Sprintf("orgs/%v/memberships/%v", org, user) method = "PUT" } else { u = fmt.Sprintf("user/memberships/orgs/%v", org) method = "PATCH" } req, err := s.client.NewRequest(method, u, membership) if err != nil { return nil, nil, err } m := new(Membership) resp, err := s.client.Do(ctx, req, m) if err != nil { return nil, resp, err } return m, resp, nil } // RemoveOrgMembership removes user from the specified organization. If the // user has been invited to the organization, this will cancel their invitation. // // GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-organization-membership func (s *OrganizationsService) RemoveOrgMembership(ctx context.Context, user, org string) (*Response, error) { u := fmt.Sprintf("orgs/%v/memberships/%v", org, user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // ListPendingOrgInvitations returns a list of pending invitations. // // GitHub API docs: https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, org string, opt *ListOptions) ([]*Invitation, *Response, error) { u := fmt.Sprintf("orgs/%v/invitations", org) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var pendingInvitations []*Invitation resp, err := s.client.Do(ctx, req, &pendingInvitations) if err != nil { return nil, resp, err } return pendingInvitations, resp, nil } // CreateOrgInvitationOptions specifies the parameters to the OrganizationService.Invite // method. type CreateOrgInvitationOptions struct { // GitHub user ID for the person you are inviting. Not required if you provide Email. InviteeID *int64 `json:"invitee_id,omitempty"` // Email address of the person you are inviting, which can be an existing GitHub user. // Not required if you provide InviteeID Email *string `json:"email,omitempty"` // Specify role for new member. Can be one of: // * admin - Organization owners with full administrative rights to the // organization and complete access to all repositories and teams. // * direct_member - Non-owner organization members with ability to see // other members and join teams by invitation. // * billing_manager - Non-owner organization members with ability to // manage the billing settings of your organization. // Default is "direct_member". Role *string `json:"role"` TeamID []int64 `json:"team_ids"` } // CreateOrgInvitation invites people to an organization by using their GitHub user ID or their email address. // 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 func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opt *CreateOrgInvitationOptions) (*Invitation, *Response, error) { u := fmt.Sprintf("orgs/%v/invitations", org) req, err := s.client.NewRequest("POST", u, opt) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview) var invitation *Invitation resp, err := s.client.Do(ctx, req, &invitation) if err != nil { return nil, resp, err } return invitation, resp, nil } // ListOrgInvitationTeams lists all teams associated with an invitation. In order to see invitations in an organization, // the authenticated user must be an organization owner. // // GitHub API docs: https://developer.github.com/v3/orgs/members/#list-organization-invitation-teams func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, invitationID string, opt *ListOptions) ([]*Team, *Response, error) { u := fmt.Sprintf("orgs/%v/invitations/%v/teams", org, invitationID) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview) var orgInvitationTeams []*Team resp, err := s.client.Do(ctx, req, &orgInvitationTeams) if err != nil { return nil, resp, err } return orgInvitationTeams, resp, nil } go-github-28.1.1/github/orgs_members_test.go000066400000000000000000000422251353501270500210320ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" "time" ) func TestOrganizationsService_ListMembers(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/members", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "filter": "2fa_disabled", "role": "admin", "page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListMembersOptions{ PublicOnly: false, Filter: "2fa_disabled", Role: "admin", ListOptions: ListOptions{Page: 2}, } members, _, err := client.Organizations.ListMembers(context.Background(), "o", opt) if err != nil { t.Errorf("Organizations.ListMembers returned error: %v", err) } want := []*User{{ID: Int64(1)}} if !reflect.DeepEqual(members, want) { t.Errorf("Organizations.ListMembers returned %+v, want %+v", members, want) } } func TestOrganizationsService_ListMembers_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Organizations.ListMembers(context.Background(), "%", nil) testURLParseError(t, err) } func TestOrganizationsService_ListMembers_public(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/public_members", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListMembersOptions{PublicOnly: true} members, _, err := client.Organizations.ListMembers(context.Background(), "o", opt) if err != nil { t.Errorf("Organizations.ListMembers returned error: %v", err) } want := []*User{{ID: Int64(1)}} if !reflect.DeepEqual(members, want) { t.Errorf("Organizations.ListMembers returned %+v, want %+v", members, want) } } func TestOrganizationsService_IsMember(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNoContent) }) member, _, err := client.Organizations.IsMember(context.Background(), "o", "u") if err != nil { t.Errorf("Organizations.IsMember returned error: %v", err) } if want := true; member != want { t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want) } } // ensure that a 404 response is interpreted as "false" and not an error func TestOrganizationsService_IsMember_notMember(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) member, _, err := client.Organizations.IsMember(context.Background(), "o", "u") if err != nil { t.Errorf("Organizations.IsMember returned error: %+v", err) } if want := false; member != want { t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want) } } // ensure that a 400 response is interpreted as an actual error, and not simply // as "false" like the above case of a 404 func TestOrganizationsService_IsMember_error(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") http.Error(w, "BadRequest", http.StatusBadRequest) }) member, _, err := client.Organizations.IsMember(context.Background(), "o", "u") if err == nil { t.Errorf("Expected HTTP 400 response") } if want := false; member != want { t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want) } } func TestOrganizationsService_IsMember_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Organizations.IsMember(context.Background(), "%", "u") testURLParseError(t, err) } func TestOrganizationsService_IsPublicMember(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNoContent) }) member, _, err := client.Organizations.IsPublicMember(context.Background(), "o", "u") if err != nil { t.Errorf("Organizations.IsPublicMember returned error: %v", err) } if want := true; member != want { t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want) } } // ensure that a 404 response is interpreted as "false" and not an error func TestOrganizationsService_IsPublicMember_notMember(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) member, _, err := client.Organizations.IsPublicMember(context.Background(), "o", "u") if err != nil { t.Errorf("Organizations.IsPublicMember returned error: %v", err) } if want := false; member != want { t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want) } } // ensure that a 400 response is interpreted as an actual error, and not simply // as "false" like the above case of a 404 func TestOrganizationsService_IsPublicMember_error(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") http.Error(w, "BadRequest", http.StatusBadRequest) }) member, _, err := client.Organizations.IsPublicMember(context.Background(), "o", "u") if err == nil { t.Errorf("Expected HTTP 400 response") } if want := false; member != want { t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want) } } func TestOrganizationsService_IsPublicMember_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Organizations.IsPublicMember(context.Background(), "%", "u") testURLParseError(t, err) } func TestOrganizationsService_RemoveMember(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Organizations.RemoveMember(context.Background(), "o", "u") if err != nil { t.Errorf("Organizations.RemoveMember returned error: %v", err) } } func TestOrganizationsService_RemoveMember_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Organizations.RemoveMember(context.Background(), "%", "u") testURLParseError(t, err) } func TestOrganizationsService_ListOrgMemberships(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/memberships/orgs", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "state": "active", "page": "2", }) fmt.Fprint(w, `[{"url":"u"}]`) }) opt := &ListOrgMembershipsOptions{ State: "active", ListOptions: ListOptions{Page: 2}, } memberships, _, err := client.Organizations.ListOrgMemberships(context.Background(), opt) if err != nil { t.Errorf("Organizations.ListOrgMemberships returned error: %v", err) } want := []*Membership{{URL: String("u")}} if !reflect.DeepEqual(memberships, want) { t.Errorf("Organizations.ListOrgMemberships returned %+v, want %+v", memberships, want) } } func TestOrganizationsService_GetOrgMembership_AuthenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/memberships/orgs/o", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"url":"u"}`) }) membership, _, err := client.Organizations.GetOrgMembership(context.Background(), "", "o") if err != nil { t.Errorf("Organizations.GetOrgMembership returned error: %v", err) } want := &Membership{URL: String("u")} if !reflect.DeepEqual(membership, want) { t.Errorf("Organizations.GetOrgMembership returned %+v, want %+v", membership, want) } } func TestOrganizationsService_GetOrgMembership_SpecifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"url":"u"}`) }) membership, _, err := client.Organizations.GetOrgMembership(context.Background(), "u", "o") if err != nil { t.Errorf("Organizations.GetOrgMembership returned error: %v", err) } want := &Membership{URL: String("u")} if !reflect.DeepEqual(membership, want) { t.Errorf("Organizations.GetOrgMembership returned %+v, want %+v", membership, want) } } func TestOrganizationsService_EditOrgMembership_AuthenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Membership{State: String("active")} mux.HandleFunc("/user/memberships/orgs/o", func(w http.ResponseWriter, r *http.Request) { v := new(Membership) 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, `{"url":"u"}`) }) membership, _, err := client.Organizations.EditOrgMembership(context.Background(), "", "o", input) if err != nil { t.Errorf("Organizations.EditOrgMembership returned error: %v", err) } want := &Membership{URL: String("u")} if !reflect.DeepEqual(membership, want) { t.Errorf("Organizations.EditOrgMembership returned %+v, want %+v", membership, want) } } func TestOrganizationsService_EditOrgMembership_SpecifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Membership{State: String("active")} mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) { v := new(Membership) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"url":"u"}`) }) membership, _, err := client.Organizations.EditOrgMembership(context.Background(), "u", "o", input) if err != nil { t.Errorf("Organizations.EditOrgMembership returned error: %v", err) } want := &Membership{URL: String("u")} if !reflect.DeepEqual(membership, want) { t.Errorf("Organizations.EditOrgMembership returned %+v, want %+v", membership, want) } } func TestOrganizationsService_RemoveOrgMembership(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Organizations.RemoveOrgMembership(context.Background(), "u", "o") if err != nil { t.Errorf("Organizations.RemoveOrgMembership returned error: %v", err) } } func TestOrganizationsService_ListPendingOrgInvitations(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/invitations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "1"}) fmt.Fprint(w, `[ { "id": 1, "login": "monalisa", "email": "octocat@github.com", "role": "direct_member", "created_at": "2017-01-21T00:00:00Z", "inviter": { "login": "other_user", "id": 1, "avatar_url": "https://github.com/images/error/other_user_happy.gif", "gravatar_id": "", "url": "https://api.github.com/users/other_user", "html_url": "https://github.com/other_user", "followers_url": "https://api.github.com/users/other_user/followers", "following_url": "https://api.github.com/users/other_user/following/other_user", "gists_url": "https://api.github.com/users/other_user/gists/gist_id", "starred_url": "https://api.github.com/users/other_user/starred/owner/repo", "subscriptions_url": "https://api.github.com/users/other_user/subscriptions", "organizations_url": "https://api.github.com/users/other_user/orgs", "repos_url": "https://api.github.com/users/other_user/repos", "events_url": "https://api.github.com/users/other_user/events/privacy", "received_events_url": "https://api.github.com/users/other_user/received_events/privacy", "type": "User", "site_admin": false }, "team_count": 2, "invitation_team_url": "https://api.github.com/organizations/2/invitations/1/teams" } ]`) }) opt := &ListOptions{Page: 1} invitations, _, err := client.Organizations.ListPendingOrgInvitations(context.Background(), "o", opt) if err != nil { t.Errorf("Organizations.ListPendingOrgInvitations returned error: %v", err) } createdAt := time.Date(2017, time.January, 21, 0, 0, 0, 0, time.UTC) want := []*Invitation{ { ID: Int64(1), Login: String("monalisa"), Email: String("octocat@github.com"), Role: String("direct_member"), CreatedAt: &createdAt, Inviter: &User{ Login: String("other_user"), ID: Int64(1), AvatarURL: String("https://github.com/images/error/other_user_happy.gif"), GravatarID: String(""), URL: String("https://api.github.com/users/other_user"), HTMLURL: String("https://github.com/other_user"), FollowersURL: String("https://api.github.com/users/other_user/followers"), FollowingURL: String("https://api.github.com/users/other_user/following/other_user"), GistsURL: String("https://api.github.com/users/other_user/gists/gist_id"), StarredURL: String("https://api.github.com/users/other_user/starred/owner/repo"), SubscriptionsURL: String("https://api.github.com/users/other_user/subscriptions"), OrganizationsURL: String("https://api.github.com/users/other_user/orgs"), ReposURL: String("https://api.github.com/users/other_user/repos"), EventsURL: String("https://api.github.com/users/other_user/events/privacy"), ReceivedEventsURL: String("https://api.github.com/users/other_user/received_events/privacy"), Type: String("User"), SiteAdmin: Bool(false), }, TeamCount: Int(2), InvitationTeamURL: String("https://api.github.com/organizations/2/invitations/1/teams"), }} if !reflect.DeepEqual(invitations, want) { t.Errorf("Organizations.ListPendingOrgInvitations returned %+v, want %+v", invitations, want) } } func TestOrganizationsService_CreateOrgInvitation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &CreateOrgInvitationOptions{ Email: String("octocat@github.com"), Role: String("direct_member"), TeamID: []int64{ 12, 26, }, } mux.HandleFunc("/orgs/o/invitations", func(w http.ResponseWriter, r *http.Request) { v := new(CreateOrgInvitationOptions) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeOrganizationInvitationPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprintln(w, `{"email": "octocat@github.com"}`) }) invitations, _, err := client.Organizations.CreateOrgInvitation(context.Background(), "o", input) if err != nil { t.Errorf("Organizations.CreateOrgInvitation returned error: %v", err) } want := &Invitation{Email: String("octocat@github.com")} if !reflect.DeepEqual(invitations, want) { t.Errorf("Organizations.ListPendingOrgInvitations returned %+v, want %+v", invitations, want) } } func TestOrganizationsService_ListOrgInvitationTeams(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/invitations/22/teams", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "1"}) testHeader(t, r, "Accept", mediaTypeOrganizationInvitationPreview) fmt.Fprint(w, `[ { "id": 1, "url": "https://api.github.com/teams/1", "name": "Justice League", "slug": "justice-league", "description": "A great team.", "privacy": "closed", "permission": "admin", "members_url": "https://api.github.com/teams/1/members{/member}", "repositories_url": "https://api.github.com/teams/1/repos" } ]`) }) opt := &ListOptions{Page: 1} invitations, _, err := client.Organizations.ListOrgInvitationTeams(context.Background(), "o", "22", opt) if err != nil { t.Errorf("Organizations.ListOrgInvitationTeams returned error: %v", err) } want := []*Team{ { ID: Int64(1), URL: String("https://api.github.com/teams/1"), Name: String("Justice League"), Slug: String("justice-league"), Description: String("A great team."), Privacy: String("closed"), Permission: String("admin"), MembersURL: String("https://api.github.com/teams/1/members{/member}"), RepositoriesURL: String("https://api.github.com/teams/1/repos"), }, } if !reflect.DeepEqual(invitations, want) { t.Errorf("Organizations.ListOrgInvitationTeams returned %+v, want %+v", invitations, want) } } go-github-28.1.1/github/orgs_outside_collaborators.go000066400000000000000000000055271353501270500227470ustar00rootroot00000000000000// Copyright 2017 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" ) // ListOutsideCollaboratorsOptions specifies optional parameters to the // OrganizationsService.ListOutsideCollaborators method. type ListOutsideCollaboratorsOptions struct { // Filter outside collaborators returned in the list. Possible values are: // 2fa_disabled, all. Default is "all". Filter string `url:"filter,omitempty"` ListOptions } // ListOutsideCollaborators lists outside collaborators of organization's repositories. // This will only work if the authenticated // user is an owner of the organization. // // Warning: The API may change without advance notice during the preview period. // Preview features are not supported for production use. // // GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#list-outside-collaborators func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org string, opt *ListOutsideCollaboratorsOptions) ([]*User, *Response, error) { u := fmt.Sprintf("orgs/%v/outside_collaborators", org) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var members []*User resp, err := s.client.Do(ctx, req, &members) if err != nil { return nil, resp, err } return members, resp, nil } // RemoveOutsideCollaborator removes a user from the list of outside collaborators; // consequently, removing them from all the organization's repositories. // // GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#remove-outside-collaborator func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // ConvertMemberToOutsideCollaborator reduces the permission level of a member of the // organization to that of an outside collaborator. Therefore, they will only // have access to the repositories that their current team membership allows. // Responses for converting a non-member or the last owner to an outside collaborator // are listed in GitHub API docs. // // GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#convert-member-to-outside-collaborator func (s *OrganizationsService) ConvertMemberToOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/orgs_outside_collaborators_test.go000066400000000000000000000105431353501270500240000ustar00rootroot00000000000000// Copyright 2017 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" "reflect" "testing" ) func TestOrganizationsService_ListOutsideCollaborators(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/outside_collaborators", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "filter": "2fa_disabled", "page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOutsideCollaboratorsOptions{ Filter: "2fa_disabled", ListOptions: ListOptions{Page: 2}, } members, _, err := client.Organizations.ListOutsideCollaborators(context.Background(), "o", opt) if err != nil { t.Errorf("Organizations.ListOutsideCollaborators returned error: %v", err) } want := []*User{{ID: Int64(1)}} if !reflect.DeepEqual(members, want) { t.Errorf("Organizations.ListOutsideCollaborators returned %+v, want %+v", members, want) } } func TestOrganizationsService_ListOutsideCollaborators_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Organizations.ListOutsideCollaborators(context.Background(), "%", nil) testURLParseError(t, err) } func TestOrganizationsService_RemoveOutsideCollaborator(t *testing.T) { client, mux, _, teardown := setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") } mux.HandleFunc("/orgs/o/outside_collaborators/u", handler) _, err := client.Organizations.RemoveOutsideCollaborator(context.Background(), "o", "u") if err != nil { t.Errorf("Organizations.RemoveOutsideCollaborator returned error: %v", err) } } func TestOrganizationsService_RemoveOutsideCollaborator_NonMember(t *testing.T) { client, mux, _, teardown := setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNotFound) } mux.HandleFunc("/orgs/o/outside_collaborators/u", handler) _, err := client.Organizations.RemoveOutsideCollaborator(context.Background(), "o", "u") if err, ok := err.(*ErrorResponse); !ok { t.Errorf("Organizations.RemoveOutsideCollaborator did not return an error") } else if err.Response.StatusCode != http.StatusNotFound { t.Errorf("Organizations.RemoveOutsideCollaborator did not return 404 status code") } } func TestOrganizationsService_RemoveOutsideCollaborator_Member(t *testing.T) { client, mux, _, teardown := setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusUnprocessableEntity) } mux.HandleFunc("/orgs/o/outside_collaborators/u", handler) _, err := client.Organizations.RemoveOutsideCollaborator(context.Background(), "o", "u") if err, ok := err.(*ErrorResponse); !ok { t.Errorf("Organizations.RemoveOutsideCollaborator did not return an error") } else if err.Response.StatusCode != http.StatusUnprocessableEntity { t.Errorf("Organizations.RemoveOutsideCollaborator did not return 422 status code") } } func TestOrganizationsService_ConvertMemberToOutsideCollaborator(t *testing.T) { client, mux, _, teardown := setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") } mux.HandleFunc("/orgs/o/outside_collaborators/u", handler) _, err := client.Organizations.ConvertMemberToOutsideCollaborator(context.Background(), "o", "u") if err != nil { t.Errorf("Organizations.ConvertMemberToOutsideCollaborator returned error: %v", err) } } func TestOrganizationsService_ConvertMemberToOutsideCollaborator_NonMemberOrLastOwner(t *testing.T) { client, mux, _, teardown := setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") w.WriteHeader(http.StatusForbidden) } mux.HandleFunc("/orgs/o/outside_collaborators/u", handler) _, err := client.Organizations.ConvertMemberToOutsideCollaborator(context.Background(), "o", "u") if err, ok := err.(*ErrorResponse); !ok { t.Errorf("Organizations.ConvertMemberToOutsideCollaborator did not return an error") } else if err.Response.StatusCode != http.StatusForbidden { t.Errorf("Organizations.ConvertMemberToOutsideCollaborator did not return 403 status code") } } go-github-28.1.1/github/orgs_projects.go000066400000000000000000000032141353501270500201650ustar00rootroot00000000000000// Copyright 2017 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" ) // ListProjects lists the projects for an organization. // // GitHub API docs: https://developer.github.com/v3/projects/#list-organization-projects func (s *OrganizationsService) ListProjects(ctx context.Context, org string, opt *ProjectListOptions) ([]*Project, *Response, error) { u := fmt.Sprintf("orgs/%v/projects", org) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) var projects []*Project resp, err := s.client.Do(ctx, req, &projects) if err != nil { return nil, resp, err } return projects, resp, nil } // CreateProject creates a GitHub Project for the specified organization. // // GitHub API docs: https://developer.github.com/v3/projects/#create-an-organization-project func (s *OrganizationsService) CreateProject(ctx context.Context, org string, opt *ProjectOptions) (*Project, *Response, error) { u := fmt.Sprintf("orgs/%v/projects", org) req, err := s.client.NewRequest("POST", u, opt) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) project := &Project{} resp, err := s.client.Do(ctx, req, project) if err != nil { return nil, resp, err } return project, resp, nil } go-github-28.1.1/github/orgs_projects_test.go000066400000000000000000000036341353501270500212320ustar00rootroot00000000000000// Copyright 2017 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestOrganizationsService_ListProjects(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/projects", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeProjectsPreview) testFormValues(t, r, values{"state": "open", "page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ProjectListOptions{State: "open", ListOptions: ListOptions{Page: 2}} projects, _, err := client.Organizations.ListProjects(context.Background(), "o", opt) if err != nil { t.Errorf("Organizations.ListProjects returned error: %v", err) } want := []*Project{{ID: Int64(1)}} if !reflect.DeepEqual(projects, want) { t.Errorf("Organizations.ListProjects returned %+v, want %+v", projects, want) } } func TestOrganizationsService_CreateProject(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ProjectOptions{Name: String("Project Name"), Body: String("Project body.")} mux.HandleFunc("/orgs/o/projects", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeProjectsPreview) v := &ProjectOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) project, _, err := client.Organizations.CreateProject(context.Background(), "o", input) if err != nil { t.Errorf("Organizations.CreateProject returned error: %v", err) } want := &Project{ID: Int64(1)} if !reflect.DeepEqual(project, want) { t.Errorf("Organizations.CreateProject returned %+v, want %+v", project, want) } } go-github-28.1.1/github/orgs_test.go000066400000000000000000000117021353501270500173140ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestOrganizationsService_ListAll(t *testing.T) { client, mux, _, teardown := setup() defer teardown() since := int64(1342004) mux.HandleFunc("/organizations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"since": "1342004"}) fmt.Fprint(w, `[{"id":4314092}]`) }) opt := &OrganizationsListOptions{Since: since} orgs, _, err := client.Organizations.ListAll(context.Background(), opt) if err != nil { t.Errorf("Organizations.ListAll returned error: %v", err) } want := []*Organization{{ID: Int64(4314092)}} if !reflect.DeepEqual(orgs, want) { t.Errorf("Organizations.ListAll returned %+v, want %+v", orgs, want) } } func TestOrganizationsService_List_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/orgs", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1},{"id":2}]`) }) orgs, _, err := client.Organizations.List(context.Background(), "", nil) if err != nil { t.Errorf("Organizations.List returned error: %v", err) } want := []*Organization{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(orgs, want) { t.Errorf("Organizations.List returned %+v, want %+v", orgs, want) } } func TestOrganizationsService_List_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/orgs", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1},{"id":2}]`) }) opt := &ListOptions{Page: 2} orgs, _, err := client.Organizations.List(context.Background(), "u", opt) if err != nil { t.Errorf("Organizations.List returned error: %v", err) } want := []*Organization{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(orgs, want) { t.Errorf("Organizations.List returned %+v, want %+v", orgs, want) } } func TestOrganizationsService_List_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Organizations.List(context.Background(), "%", nil) testURLParseError(t, err) } func TestOrganizationsService_Get(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeMemberAllowedRepoCreationTypePreview) fmt.Fprint(w, `{"id":1, "login":"l", "url":"u", "avatar_url": "a", "location":"l"}`) }) org, _, err := client.Organizations.Get(context.Background(), "o") if err != nil { t.Errorf("Organizations.Get returned error: %v", err) } want := &Organization{ID: Int64(1), Login: String("l"), URL: String("u"), AvatarURL: String("a"), Location: String("l")} if !reflect.DeepEqual(org, want) { t.Errorf("Organizations.Get returned %+v, want %+v", org, want) } } func TestOrganizationsService_Get_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Organizations.Get(context.Background(), "%") testURLParseError(t, err) } func TestOrganizationsService_GetByID(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/organizations/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1, "login":"l", "url":"u", "avatar_url": "a", "location":"l"}`) }) org, _, err := client.Organizations.GetByID(context.Background(), 1) if err != nil { t.Fatalf("Organizations.GetByID returned error: %v", err) } want := &Organization{ID: Int64(1), Login: String("l"), URL: String("u"), AvatarURL: String("a"), Location: String("l")} if !reflect.DeepEqual(org, want) { t.Errorf("Organizations.GetByID returned %+v, want %+v", org, want) } } func TestOrganizationsService_Edit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Organization{Login: String("l")} mux.HandleFunc("/orgs/o", func(w http.ResponseWriter, r *http.Request) { v := new(Organization) 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}`) }) org, _, err := client.Organizations.Edit(context.Background(), "o", input) if err != nil { t.Errorf("Organizations.Edit returned error: %v", err) } want := &Organization{ID: Int64(1)} if !reflect.DeepEqual(org, want) { t.Errorf("Organizations.Edit returned %+v, want %+v", org, want) } } func TestOrganizationsService_Edit_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Organizations.Edit(context.Background(), "%", nil) testURLParseError(t, err) } go-github-28.1.1/github/orgs_users_blocking.go000066400000000000000000000053461353501270500213550ustar00rootroot00000000000000// Copyright 2017 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" ) // ListBlockedUsers lists all the users blocked by an organization. // // GitHub API docs: https://developer.github.com/v3/orgs/blocking/#list-blocked-users func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, opt *ListOptions) ([]*User, *Response, error) { u := fmt.Sprintf("orgs/%v/blocks", org) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeBlockUsersPreview) var blockedUsers []*User resp, err := s.client.Do(ctx, req, &blockedUsers) if err != nil { return nil, resp, err } return blockedUsers, resp, nil } // IsBlocked reports whether specified user is blocked from an organization. // // GitHub API docs: https://developer.github.com/v3/orgs/blocking/#check-whether-a-user-is-blocked-from-an-organization func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user string) (bool, *Response, error) { u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeBlockUsersPreview) resp, err := s.client.Do(ctx, req, nil) isBlocked, err := parseBoolResponse(err) return isBlocked, resp, err } // BlockUser blocks specified user from an organization. // // GitHub API docs: https://developer.github.com/v3/orgs/blocking/#block-a-user func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeBlockUsersPreview) return s.client.Do(ctx, req, nil) } // UnblockUser unblocks specified user from an organization. // // GitHub API docs: https://developer.github.com/v3/orgs/blocking/#unblock-a-user func (s *OrganizationsService) UnblockUser(ctx context.Context, org string, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeBlockUsersPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/orgs_users_blocking_test.go000066400000000000000000000050601353501270500224050ustar00rootroot00000000000000// Copyright 2017 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" "reflect" "testing" ) func TestOrganizationsService_ListBlockedUsers(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/blocks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeBlockUsersPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{ "login": "octocat" }]`) }) opt := &ListOptions{Page: 2} blockedUsers, _, err := client.Organizations.ListBlockedUsers(context.Background(), "o", opt) if err != nil { t.Errorf("Organizations.ListBlockedUsers returned error: %v", err) } want := []*User{{Login: String("octocat")}} if !reflect.DeepEqual(blockedUsers, want) { t.Errorf("Organizations.ListBlockedUsers returned %+v, want %+v", blockedUsers, want) } } func TestOrganizationsService_IsBlocked(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/blocks/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeBlockUsersPreview) w.WriteHeader(http.StatusNoContent) }) isBlocked, _, err := client.Organizations.IsBlocked(context.Background(), "o", "u") if err != nil { t.Errorf("Organizations.IsBlocked returned error: %v", err) } if want := true; isBlocked != want { t.Errorf("Organizations.IsBlocked returned %+v, want %+v", isBlocked, want) } } func TestOrganizationsService_BlockUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/blocks/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeBlockUsersPreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Organizations.BlockUser(context.Background(), "o", "u") if err != nil { t.Errorf("Organizations.BlockUser returned error: %v", err) } } func TestOrganizationsService_UnblockUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/blocks/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeBlockUsersPreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Organizations.UnblockUser(context.Background(), "o", "u") if err != nil { t.Errorf("Organizations.UnblockUser returned error: %v", err) } } go-github-28.1.1/github/projects.go000066400000000000000000000513141353501270500171370ustar00rootroot00000000000000// 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" ) // ProjectsService provides access to the projects functions in the // GitHub API. // // GitHub API docs: https://developer.github.com/v3/projects/ type ProjectsService service // Project represents a GitHub Project. type Project struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` ColumnsURL *string `json:"columns_url,omitempty"` OwnerURL *string `json:"owner_url,omitempty"` Name *string `json:"name,omitempty"` Body *string `json:"body,omitempty"` Number *int `json:"number,omitempty"` State *string `json:"state,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` NodeID *string `json:"node_id,omitempty"` // The User object that generated the project. Creator *User `json:"creator,omitempty"` } func (p Project) String() string { return Stringify(p) } // GetProject gets a GitHub Project for a repo. // // GitHub API docs: https://developer.github.com/v3/projects/#get-a-project func (s *ProjectsService) GetProject(ctx context.Context, id int64) (*Project, *Response, error) { u := fmt.Sprintf("projects/%v", id) 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", mediaTypeProjectsPreview) project := &Project{} resp, err := s.client.Do(ctx, req, project) if err != nil { return nil, resp, err } return project, resp, nil } // ProjectOptions specifies the parameters to the // RepositoriesService.CreateProject and // ProjectsService.UpdateProject methods. type ProjectOptions struct { // The name of the project. (Required for creation; optional for update.) Name *string `json:"name,omitempty"` // The body of the project. (Optional.) Body *string `json:"body,omitempty"` // The following field(s) are only applicable for update. // They should be left with zero values for creation. // State of the project. Either "open" or "closed". (Optional.) State *string `json:"state,omitempty"` // The permission level that all members of the project's organization // will have on this project. // Setting the organization permission is only available // for organization projects. (Optional.) OrganizationPermission *string `json:"organization_permission,omitempty"` // Sets visibility of the project within the organization. // Setting visibility is only available // for organization projects.(Optional.) Public *bool `json:"public,omitempty"` } // UpdateProject updates a repository project. // // GitHub API docs: https://developer.github.com/v3/projects/#update-a-project func (s *ProjectsService) UpdateProject(ctx context.Context, id int64, opt *ProjectOptions) (*Project, *Response, error) { u := fmt.Sprintf("projects/%v", id) req, err := s.client.NewRequest("PATCH", u, opt) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. req.Header.Set("Accept", mediaTypeProjectsPreview) project := &Project{} resp, err := s.client.Do(ctx, req, project) if err != nil { return nil, resp, err } return project, resp, nil } // DeleteProject deletes a GitHub Project from a repository. // // GitHub API docs: https://developer.github.com/v3/projects/#delete-a-project func (s *ProjectsService) DeleteProject(ctx context.Context, id int64) (*Response, error) { u := fmt.Sprintf("projects/%v", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) return s.client.Do(ctx, req, nil) } // ProjectColumn represents a column of a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/repos/projects/ type ProjectColumn struct { ID *int64 `json:"id,omitempty"` Name *string `json:"name,omitempty"` URL *string `json:"url,omitempty"` ProjectURL *string `json:"project_url,omitempty"` CardsURL *string `json:"cards_url,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` NodeID *string `json:"node_id,omitempty"` } // ListProjectColumns lists the columns of a GitHub Project for a repo. // // GitHub API docs: https://developer.github.com/v3/projects/columns/#list-project-columns func (s *ProjectsService) ListProjectColumns(ctx context.Context, projectID int64, opt *ListOptions) ([]*ProjectColumn, *Response, error) { u := fmt.Sprintf("projects/%v/columns", projectID) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. req.Header.Set("Accept", mediaTypeProjectsPreview) columns := []*ProjectColumn{} resp, err := s.client.Do(ctx, req, &columns) if err != nil { return nil, resp, err } return columns, resp, nil } // GetProjectColumn gets a column of a GitHub Project for a repo. // // GitHub API docs: https://developer.github.com/v3/projects/columns/#get-a-project-column func (s *ProjectsService) GetProjectColumn(ctx context.Context, id int64) (*ProjectColumn, *Response, error) { u := fmt.Sprintf("projects/columns/%v", id) 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", mediaTypeProjectsPreview) column := &ProjectColumn{} resp, err := s.client.Do(ctx, req, column) if err != nil { return nil, resp, err } return column, resp, nil } // ProjectColumnOptions specifies the parameters to the // ProjectsService.CreateProjectColumn and // ProjectsService.UpdateProjectColumn methods. type ProjectColumnOptions struct { // The name of the project column. (Required for creation and update.) Name string `json:"name"` } // CreateProjectColumn creates a column for the specified (by number) project. // // GitHub API docs: https://developer.github.com/v3/projects/columns/#create-a-project-column func (s *ProjectsService) CreateProjectColumn(ctx context.Context, projectID int64, opt *ProjectColumnOptions) (*ProjectColumn, *Response, error) { u := fmt.Sprintf("projects/%v/columns", projectID) req, err := s.client.NewRequest("POST", u, opt) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. req.Header.Set("Accept", mediaTypeProjectsPreview) column := &ProjectColumn{} resp, err := s.client.Do(ctx, req, column) if err != nil { return nil, resp, err } return column, resp, nil } // UpdateProjectColumn updates a column of a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/projects/columns/#update-a-project-column func (s *ProjectsService) UpdateProjectColumn(ctx context.Context, columnID int64, opt *ProjectColumnOptions) (*ProjectColumn, *Response, error) { u := fmt.Sprintf("projects/columns/%v", columnID) req, err := s.client.NewRequest("PATCH", u, opt) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. req.Header.Set("Accept", mediaTypeProjectsPreview) column := &ProjectColumn{} resp, err := s.client.Do(ctx, req, column) if err != nil { return nil, resp, err } return column, resp, nil } // DeleteProjectColumn deletes a column from a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/projects/columns/#delete-a-project-column func (s *ProjectsService) DeleteProjectColumn(ctx context.Context, columnID int64) (*Response, error) { u := fmt.Sprintf("projects/columns/%v", columnID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) return s.client.Do(ctx, req, nil) } // ProjectColumnMoveOptions specifies the parameters to the // ProjectsService.MoveProjectColumn method. type ProjectColumnMoveOptions struct { // Position can be one of "first", "last", or "after:", where // is the ID of a column in the same project. (Required.) Position string `json:"position"` } // MoveProjectColumn moves a column within a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/projects/columns/#move-a-project-column func (s *ProjectsService) MoveProjectColumn(ctx context.Context, columnID int64, opt *ProjectColumnMoveOptions) (*Response, error) { u := fmt.Sprintf("projects/columns/%v/moves", columnID) req, err := s.client.NewRequest("POST", u, opt) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) return s.client.Do(ctx, req, nil) } // ProjectCard represents a card in a column of a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card type ProjectCard struct { URL *string `json:"url,omitempty"` ColumnURL *string `json:"column_url,omitempty"` ContentURL *string `json:"content_url,omitempty"` ID *int64 `json:"id,omitempty"` Note *string `json:"note,omitempty"` Creator *User `json:"creator,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` NodeID *string `json:"node_id,omitempty"` Archived *bool `json:"archived,omitempty"` // The following fields are only populated by Webhook events. ColumnID *int64 `json:"column_id,omitempty"` // The following fields are only populated by Events API. ProjectID *int64 `json:"project_id,omitempty"` ProjectURL *string `json:"project_url,omitempty"` ColumnName *string `json:"column_name,omitempty"` PreviousColumnName *string `json:"previous_column_name,omitempty"` // Populated in "moved_columns_in_project" event deliveries. } // ProjectCardListOptions specifies the optional parameters to the // ProjectsService.ListProjectCards method. type ProjectCardListOptions struct { // ArchivedState is used to list all, archived, or not_archived project cards. // Defaults to not_archived when you omit this parameter. ArchivedState *string `url:"archived_state,omitempty"` ListOptions } // ListProjectCards lists the cards in a column of a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/projects/cards/#list-project-cards func (s *ProjectsService) ListProjectCards(ctx context.Context, columnID int64, opt *ProjectCardListOptions) ([]*ProjectCard, *Response, error) { u := fmt.Sprintf("projects/columns/%v/cards", columnID) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. req.Header.Set("Accept", mediaTypeProjectsPreview) cards := []*ProjectCard{} resp, err := s.client.Do(ctx, req, &cards) if err != nil { return nil, resp, err } return cards, resp, nil } // GetProjectCard gets a card in a column of a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card func (s *ProjectsService) GetProjectCard(ctx context.Context, cardID int64) (*ProjectCard, *Response, error) { u := fmt.Sprintf("projects/columns/cards/%v", cardID) 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", mediaTypeProjectsPreview) card := &ProjectCard{} resp, err := s.client.Do(ctx, req, card) if err != nil { return nil, resp, err } return card, resp, nil } // ProjectCardOptions specifies the parameters to the // ProjectsService.CreateProjectCard and // ProjectsService.UpdateProjectCard methods. type ProjectCardOptions struct { // The note of the card. Note and ContentID are mutually exclusive. Note string `json:"note,omitempty"` // The ID (not Number) of the Issue to associate with this card. // Note and ContentID are mutually exclusive. ContentID int64 `json:"content_id,omitempty"` // The type of content to associate with this card. Possible values are: "Issue" and "PullRequest". ContentType string `json:"content_type,omitempty"` // Use true to archive a project card. // Specify false if you need to restore a previously archived project card. Archived *bool `json:"archived,omitempty"` } // CreateProjectCard creates a card in the specified column of a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/projects/cards/#create-a-project-card func (s *ProjectsService) CreateProjectCard(ctx context.Context, columnID int64, opt *ProjectCardOptions) (*ProjectCard, *Response, error) { u := fmt.Sprintf("projects/columns/%v/cards", columnID) req, err := s.client.NewRequest("POST", u, opt) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. req.Header.Set("Accept", mediaTypeProjectsPreview) card := &ProjectCard{} resp, err := s.client.Do(ctx, req, card) if err != nil { return nil, resp, err } return card, resp, nil } // UpdateProjectCard updates a card of a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/projects/cards/#update-a-project-card func (s *ProjectsService) UpdateProjectCard(ctx context.Context, cardID int64, opt *ProjectCardOptions) (*ProjectCard, *Response, error) { u := fmt.Sprintf("projects/columns/cards/%v", cardID) req, err := s.client.NewRequest("PATCH", u, opt) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. req.Header.Set("Accept", mediaTypeProjectsPreview) card := &ProjectCard{} resp, err := s.client.Do(ctx, req, card) if err != nil { return nil, resp, err } return card, resp, nil } // DeleteProjectCard deletes a card from a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/projects/cards/#delete-a-project-card func (s *ProjectsService) DeleteProjectCard(ctx context.Context, cardID int64) (*Response, error) { u := fmt.Sprintf("projects/columns/cards/%v", cardID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) return s.client.Do(ctx, req, nil) } // ProjectCardMoveOptions specifies the parameters to the // ProjectsService.MoveProjectCard method. type ProjectCardMoveOptions struct { // Position can be one of "top", "bottom", or "after:", where // is the ID of a card in the same project. Position string `json:"position"` // ColumnID is the ID of a column in the same project. Note that ColumnID // is required when using Position "after:" when that card is in // another column; otherwise it is optional. ColumnID int64 `json:"column_id,omitempty"` } // MoveProjectCard moves a card within a GitHub Project. // // GitHub API docs: https://developer.github.com/v3/projects/cards/#move-a-project-card func (s *ProjectsService) MoveProjectCard(ctx context.Context, cardID int64, opt *ProjectCardMoveOptions) (*Response, error) { u := fmt.Sprintf("projects/columns/cards/%v/moves", cardID) req, err := s.client.NewRequest("POST", u, opt) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) return s.client.Do(ctx, req, nil) } // ProjectCollaboratorOptions specifies the optional parameters to the // ProjectsService.AddProjectCollaborator method. type ProjectCollaboratorOptions struct { // Permission specifies the permission to grant to the collaborator. // Possible values are: // "read" - can read, but not write to or administer this project. // "write" - can read and write, but not administer this project. // "admin" - can read, write and administer this project. // // Default value is "write" Permission *string `json:"permission,omitempty"` } // AddProjectCollaborator adds a collaborator to an organization project and sets // their permission level. You must be an organization owner or a project admin to add a collaborator. // // GitHub API docs: https://developer.github.com/v3/projects/collaborators/#add-user-as-a-collaborator func (s *ProjectsService) AddProjectCollaborator(ctx context.Context, id int64, username string, opt *ProjectCollaboratorOptions) (*Response, error) { u := fmt.Sprintf("projects/%v/collaborators/%v", id, username) req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) return s.client.Do(ctx, req, nil) } // RemoveProjectCollaborator removes a collaborator from an organization project. // You must be an organization owner or a project admin to remove a collaborator. // // GitHub API docs: https://developer.github.com/v3/projects/collaborators/#remove-user-as-a-collaborator func (s *ProjectsService) RemoveProjectCollaborator(ctx context.Context, id int64, username string) (*Response, error) { u := fmt.Sprintf("projects/%v/collaborators/%v", id, username) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) return s.client.Do(ctx, req, nil) } // ListCollaboratorOptions specifies the optional parameters to the // ProjectsService.ListProjectCollaborators method. type ListCollaboratorOptions struct { // Affiliation specifies how collaborators should be filtered by their affiliation. // Possible values are: // "outside" - All outside collaborators of an organization-owned repository // "direct" - All collaborators with permissions to an organization-owned repository, // regardless of organization membership status // "all" - All collaborators the authenticated user can see // // Default value is "all". Affiliation *string `url:"affiliation,omitempty"` ListOptions } // ListProjectCollaborators lists the collaborators for an organization project. For a project, // the list of collaborators includes outside collaborators, organization members that are direct // collaborators, organization members with access through team memberships, organization members // with access through default organization permissions, and organization owners. You must be an // organization owner or a project admin to list collaborators. // // GitHub API docs: https://developer.github.com/v3/projects/collaborators/#list-collaborators func (s *ProjectsService) ListProjectCollaborators(ctx context.Context, id int64, opt *ListCollaboratorOptions) ([]*User, *Response, error) { u := fmt.Sprintf("projects/%v/collaborators", id) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) var users []*User resp, err := s.client.Do(ctx, req, &users) if err != nil { return nil, resp, err } return users, resp, nil } // ProjectPermissionLevel represents the permission level an organization // member has for a given project. type ProjectPermissionLevel struct { // Possible values: "admin", "write", "read", "none" Permission *string `json:"permission,omitempty"` User *User `json:"user,omitempty"` } // ReviewProjectCollaboratorPermission returns the collaborator's permission level for an organization // project. Possible values for the permission key: "admin", "write", "read", "none". // You must be an organization owner or a project admin to review a user's permission level. // // GitHub API docs: https://developer.github.com/v3/projects/collaborators/#review-a-users-permission-level func (s *ProjectsService) ReviewProjectCollaboratorPermission(ctx context.Context, id int64, username string) (*ProjectPermissionLevel, *Response, error) { u := fmt.Sprintf("projects/%v/collaborators/%v/permission", id, username) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeProjectsPreview) ppl := new(ProjectPermissionLevel) resp, err := s.client.Do(ctx, req, ppl) if err != nil { return nil, resp, err } return ppl, resp, nil } go-github-28.1.1/github/projects_test.go000066400000000000000000000406251353501270500202010ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "strings" "testing" ) func TestProject_marshall(t *testing.T) { testJSONMarshal(t, &Project{}, "{}") u := &Project{ ID: Int64(1), URL: String("u"), HTMLURL: String("h"), ColumnsURL: String("c"), OwnerURL: String("o"), Name: String("n"), Body: String("b"), Number: Int(1), State: String("s"), CreatedAt: &Timestamp{referenceTime}, UpdatedAt: &Timestamp{referenceTime}, NodeID: String("n"), Creator: &User{ Login: String("l"), ID: Int64(1), AvatarURL: String("a"), GravatarID: String("g"), Name: String("n"), Company: String("c"), Blog: String("b"), Location: String("l"), Email: String("e"), Hireable: Bool(true), PublicRepos: Int(1), Followers: Int(1), Following: Int(1), CreatedAt: &Timestamp{referenceTime}, URL: String("u"), }, } want := `{ "id": 1, "url": "u", "html_url": "h", "columns_url": "c", "owner_url": "o", "name": "n", "body": "b", "number": 1, "state": "s", "created_at": ` + referenceTimeStr + `, "updated_at": ` + referenceTimeStr + `, "node_id": "n", "creator": { "login": "l", "id": 1, "avatar_url": "a", "gravatar_id": "g", "name": "n", "company": "c", "blog": "b", "location": "l", "email": "e", "hireable": true, "public_repos": 1, "followers": 1, "following": 1, "created_at": ` + referenceTimeStr + `, "url": "u" } }` testJSONMarshal(t, u, want) } func TestProjectsService_UpdateProject(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ProjectOptions{ Name: String("Project Name"), Body: String("Project body."), State: String("open"), Public: Bool(true), OrganizationPermission: String("read"), } mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeProjectsPreview) v := &ProjectOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) project, _, err := client.Projects.UpdateProject(context.Background(), 1, input) if err != nil { t.Errorf("Projects.UpdateProject returned error: %v", err) } want := &Project{ID: Int64(1)} if !reflect.DeepEqual(project, want) { t.Errorf("Projects.UpdateProject returned %+v, want %+v", project, want) } } func TestProjectsService_GetProject(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeProjectsPreview) fmt.Fprint(w, `{"id":1}`) }) project, _, err := client.Projects.GetProject(context.Background(), 1) if err != nil { t.Errorf("Projects.GetProject returned error: %v", err) } want := &Project{ID: Int64(1)} if !reflect.DeepEqual(project, want) { t.Errorf("Projects.GetProject returned %+v, want %+v", project, want) } } func TestProjectsService_DeleteProject(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeProjectsPreview) }) _, err := client.Projects.DeleteProject(context.Background(), 1) if err != nil { t.Errorf("Projects.DeleteProject returned error: %v", err) } } func TestProjectsService_ListProjectColumns(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeProjectsPreview} mux.HandleFunc("/projects/1/columns", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} columns, _, err := client.Projects.ListProjectColumns(context.Background(), 1, opt) if err != nil { t.Errorf("Projects.ListProjectColumns returned error: %v", err) } want := []*ProjectColumn{{ID: Int64(1)}} if !reflect.DeepEqual(columns, want) { t.Errorf("Projects.ListProjectColumns returned %+v, want %+v", columns, want) } } func TestProjectsService_GetProjectColumn(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeProjectsPreview) fmt.Fprint(w, `{"id":1}`) }) column, _, err := client.Projects.GetProjectColumn(context.Background(), 1) if err != nil { t.Errorf("Projects.GetProjectColumn returned error: %v", err) } want := &ProjectColumn{ID: Int64(1)} if !reflect.DeepEqual(column, want) { t.Errorf("Projects.GetProjectColumn returned %+v, want %+v", column, want) } } func TestProjectsService_CreateProjectColumn(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ProjectColumnOptions{Name: "Column Name"} mux.HandleFunc("/projects/1/columns", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeProjectsPreview) v := &ProjectColumnOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) column, _, err := client.Projects.CreateProjectColumn(context.Background(), 1, input) if err != nil { t.Errorf("Projects.CreateProjectColumn returned error: %v", err) } want := &ProjectColumn{ID: Int64(1)} if !reflect.DeepEqual(column, want) { t.Errorf("Projects.CreateProjectColumn returned %+v, want %+v", column, want) } } func TestProjectsService_UpdateProjectColumn(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ProjectColumnOptions{Name: "Column Name"} mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeProjectsPreview) v := &ProjectColumnOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) column, _, err := client.Projects.UpdateProjectColumn(context.Background(), 1, input) if err != nil { t.Errorf("Projects.UpdateProjectColumn returned error: %v", err) } want := &ProjectColumn{ID: Int64(1)} if !reflect.DeepEqual(column, want) { t.Errorf("Projects.UpdateProjectColumn returned %+v, want %+v", column, want) } } func TestProjectsService_DeleteProjectColumn(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeProjectsPreview) }) _, err := client.Projects.DeleteProjectColumn(context.Background(), 1) if err != nil { t.Errorf("Projects.DeleteProjectColumn returned error: %v", err) } } func TestProjectsService_MoveProjectColumn(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ProjectColumnMoveOptions{Position: "after:12345"} mux.HandleFunc("/projects/columns/1/moves", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeProjectsPreview) v := &ProjectColumnMoveOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } }) _, err := client.Projects.MoveProjectColumn(context.Background(), 1, input) if err != nil { t.Errorf("Projects.MoveProjectColumn returned error: %v", err) } } func TestProjectsService_ListProjectCards(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/columns/1/cards", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeProjectsPreview) testFormValues(t, r, values{ "archived_state": "all", "page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ProjectCardListOptions{ ArchivedState: String("all"), ListOptions: ListOptions{Page: 2}} cards, _, err := client.Projects.ListProjectCards(context.Background(), 1, opt) if err != nil { t.Errorf("Projects.ListProjectCards returned error: %v", err) } want := []*ProjectCard{{ID: Int64(1)}} if !reflect.DeepEqual(cards, want) { t.Errorf("Projects.ListProjectCards returned %+v, want %+v", cards, want) } } func TestProjectsService_GetProjectCard(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeProjectsPreview) fmt.Fprint(w, `{"id":1}`) }) card, _, err := client.Projects.GetProjectCard(context.Background(), 1) if err != nil { t.Errorf("Projects.GetProjectCard returned error: %v", err) } want := &ProjectCard{ID: Int64(1)} if !reflect.DeepEqual(card, want) { t.Errorf("Projects.GetProjectCard returned %+v, want %+v", card, want) } } func TestProjectsService_CreateProjectCard(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ProjectCardOptions{ ContentID: 12345, ContentType: "Issue", } mux.HandleFunc("/projects/columns/1/cards", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeProjectsPreview) v := &ProjectCardOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) card, _, err := client.Projects.CreateProjectCard(context.Background(), 1, input) if err != nil { t.Errorf("Projects.CreateProjectCard returned error: %v", err) } want := &ProjectCard{ID: Int64(1)} if !reflect.DeepEqual(card, want) { t.Errorf("Projects.CreateProjectCard returned %+v, want %+v", card, want) } } func TestProjectsService_UpdateProjectCard(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ProjectCardOptions{ ContentID: 12345, ContentType: "Issue", } mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeProjectsPreview) v := &ProjectCardOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1, "archived":false}`) }) card, _, err := client.Projects.UpdateProjectCard(context.Background(), 1, input) if err != nil { t.Errorf("Projects.UpdateProjectCard returned error: %v", err) } want := &ProjectCard{ID: Int64(1), Archived: Bool(false)} if !reflect.DeepEqual(card, want) { t.Errorf("Projects.UpdateProjectCard returned %+v, want %+v", card, want) } } func TestProjectsService_DeleteProjectCard(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeProjectsPreview) }) _, err := client.Projects.DeleteProjectCard(context.Background(), 1) if err != nil { t.Errorf("Projects.DeleteProjectCard returned error: %v", err) } } func TestProjectsService_MoveProjectCard(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ProjectCardMoveOptions{Position: "after:12345"} mux.HandleFunc("/projects/columns/cards/1/moves", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeProjectsPreview) v := &ProjectCardMoveOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } }) _, err := client.Projects.MoveProjectCard(context.Background(), 1, input) if err != nil { t.Errorf("Projects.MoveProjectCard returned error: %v", err) } } func TestProjectsService_AddProjectCollaborator(t *testing.T) { client, mux, _, teardown := setup() defer teardown() opt := &ProjectCollaboratorOptions{ Permission: String("admin"), } mux.HandleFunc("/projects/1/collaborators/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeProjectsPreview) v := &ProjectCollaboratorOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, opt) { t.Errorf("Request body = %+v, want %+v", v, opt) } w.WriteHeader(http.StatusNoContent) }) _, err := client.Projects.AddProjectCollaborator(context.Background(), 1, "u", opt) if err != nil { t.Errorf("Projects.AddProjectCollaborator returned error: %v", err) } } func TestProjectsService_AddCollaborator_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Projects.AddProjectCollaborator(context.Background(), 1, "%", nil) testURLParseError(t, err) } func TestProjectsService_RemoveCollaborator(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/1/collaborators/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeProjectsPreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Projects.RemoveProjectCollaborator(context.Background(), 1, "u") if err != nil { t.Errorf("Projects.RemoveProjectCollaborator returned error: %v", err) } } func TestProjectsService_RemoveCollaborator_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Projects.RemoveProjectCollaborator(context.Background(), 1, "%") testURLParseError(t, err) } func TestProjectsService_ListCollaborators(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/1/collaborators", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeProjectsPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprintf(w, `[{"id":1}, {"id":2}]`) }) opt := &ListCollaboratorOptions{ ListOptions: ListOptions{Page: 2}, } users, _, err := client.Projects.ListProjectCollaborators(context.Background(), 1, opt) if err != nil { t.Errorf("Projects.ListProjectCollaborators returned error: %v", err) } want := []*User{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(users, want) { t.Errorf("Projects.ListProjectCollaborators returned %+v, want %+v", users, want) } } func TestProjectsService_ListCollaborators_withAffiliation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/1/collaborators", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeProjectsPreview) testFormValues(t, r, values{"affiliation": "all", "page": "2"}) fmt.Fprintf(w, `[{"id":1}, {"id":2}]`) }) opt := &ListCollaboratorOptions{ ListOptions: ListOptions{Page: 2}, Affiliation: String("all"), } users, _, err := client.Projects.ListProjectCollaborators(context.Background(), 1, opt) if err != nil { t.Errorf("Projects.ListProjectCollaborators returned error: %v", err) } want := []*User{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(users, want) { t.Errorf("Projects.ListProjectCollaborators returned %+v, want %+v", users, want) } } func TestProjectsService_GetPermissionLevel(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/projects/1/collaborators/u/permission", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeProjectsPreview) fmt.Fprintf(w, `{"permission":"admin","user":{"login":"u"}}`) }) ppl, _, err := client.Projects.ReviewProjectCollaboratorPermission(context.Background(), 1, "u") if err != nil { t.Errorf("Projects.ReviewProjectCollaboratorPermission returned error: %v", err) } want := &ProjectPermissionLevel{ Permission: String("admin"), User: &User{ Login: String("u"), }, } if !reflect.DeepEqual(ppl, want) { t.Errorf("Projects.ReviewProjectCollaboratorPermission returned %+v, want %+v", ppl, want) } } go-github-28.1.1/github/pulls.go000066400000000000000000000423651353501270500164530ustar00rootroot00000000000000// 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 ( "bytes" "context" "fmt" "strings" "time" ) // PullRequestsService handles communication with the pull request related // methods of the GitHub API. // // GitHub API docs: https://developer.github.com/v3/pulls/ type PullRequestsService service // PullRequest represents a GitHub pull request on a repository. type PullRequest struct { ID *int64 `json:"id,omitempty"` Number *int `json:"number,omitempty"` State *string `json:"state,omitempty"` Locked *bool `json:"locked,omitempty"` Title *string `json:"title,omitempty"` Body *string `json:"body,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` ClosedAt *time.Time `json:"closed_at,omitempty"` MergedAt *time.Time `json:"merged_at,omitempty"` Labels []*Label `json:"labels,omitempty"` User *User `json:"user,omitempty"` Draft *bool `json:"draft,omitempty"` Merged *bool `json:"merged,omitempty"` Mergeable *bool `json:"mergeable,omitempty"` MergeableState *string `json:"mergeable_state,omitempty"` MergedBy *User `json:"merged_by,omitempty"` MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` Rebaseable *bool `json:"rebaseable,omitempty"` Comments *int `json:"comments,omitempty"` Commits *int `json:"commits,omitempty"` Additions *int `json:"additions,omitempty"` Deletions *int `json:"deletions,omitempty"` ChangedFiles *int `json:"changed_files,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` IssueURL *string `json:"issue_url,omitempty"` StatusesURL *string `json:"statuses_url,omitempty"` DiffURL *string `json:"diff_url,omitempty"` PatchURL *string `json:"patch_url,omitempty"` CommitsURL *string `json:"commits_url,omitempty"` CommentsURL *string `json:"comments_url,omitempty"` ReviewCommentsURL *string `json:"review_comments_url,omitempty"` ReviewCommentURL *string `json:"review_comment_url,omitempty"` ReviewComments *int `json:"review_comments,omitempty"` Assignee *User `json:"assignee,omitempty"` Assignees []*User `json:"assignees,omitempty"` Milestone *Milestone `json:"milestone,omitempty"` MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` AuthorAssociation *string `json:"author_association,omitempty"` NodeID *string `json:"node_id,omitempty"` RequestedReviewers []*User `json:"requested_reviewers,omitempty"` // RequestedTeams is populated as part of the PullRequestEvent. // See, https://developer.github.com/v3/activity/events/types/#pullrequestevent for an example. RequestedTeams []*Team `json:"requested_teams,omitempty"` Links *PRLinks `json:"_links,omitempty"` Head *PullRequestBranch `json:"head,omitempty"` Base *PullRequestBranch `json:"base,omitempty"` // ActiveLockReason is populated only when LockReason is provided while locking the pull request. // Possible values are: "off-topic", "too heated", "resolved", and "spam". ActiveLockReason *string `json:"active_lock_reason,omitempty"` } func (p PullRequest) String() string { return Stringify(p) } // PRLink represents a single link object from Github pull request _links. type PRLink struct { HRef *string `json:"href,omitempty"` } // PRLinks represents the "_links" object in a Github pull request. type PRLinks struct { Self *PRLink `json:"self,omitempty"` HTML *PRLink `json:"html,omitempty"` Issue *PRLink `json:"issue,omitempty"` Comments *PRLink `json:"comments,omitempty"` ReviewComments *PRLink `json:"review_comments,omitempty"` ReviewComment *PRLink `json:"review_comment,omitempty"` Commits *PRLink `json:"commits,omitempty"` Statuses *PRLink `json:"statuses,omitempty"` } // PullRequestBranch represents a base or head branch in a GitHub pull request. type PullRequestBranch struct { Label *string `json:"label,omitempty"` Ref *string `json:"ref,omitempty"` SHA *string `json:"sha,omitempty"` Repo *Repository `json:"repo,omitempty"` User *User `json:"user,omitempty"` } // PullRequestListOptions specifies the optional parameters to the // PullRequestsService.List method. type PullRequestListOptions struct { // State filters pull requests based on their state. Possible values are: // open, closed, all. Default is "open". State string `url:"state,omitempty"` // Head filters pull requests by head user and branch name in the format of: // "user:ref-name". Head string `url:"head,omitempty"` // Base filters pull requests by base branch name. Base string `url:"base,omitempty"` // Sort specifies how to sort pull requests. Possible values are: created, // updated, popularity, long-running. Default is "created". Sort string `url:"sort,omitempty"` // Direction in which to sort pull requests. Possible values are: asc, desc. // If Sort is "created" or not specified, Default is "desc", otherwise Default // is "asc" Direction string `url:"direction,omitempty"` ListOptions } // List the pull requests for the specified repository. // // GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests func (s *PullRequestsService) List(ctx context.Context, owner string, repo string, opt *PullRequestListOptions) ([]*PullRequest, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview, mediaTypeDraftPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var pulls []*PullRequest resp, err := s.client.Do(ctx, req, &pulls) if err != nil { return nil, resp, err } return pulls, resp, nil } // ListPullRequestsWithCommit returns pull requests associated with a commit SHA. // // The results will include open and closed pull requests. // // GitHub API docs: https://developer.github.com/v3/repos/commits/#list-pull-requests-associated-with-commit func (s *PullRequestsService) ListPullRequestsWithCommit(ctx context.Context, owner, repo, sha string, opt *PullRequestListOptions) ([]*PullRequest, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/pulls", owner, repo, sha) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeListPullsOrBranchesForCommitPreview, mediaTypeDraftPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var pulls []*PullRequest resp, err := s.client.Do(ctx, req, &pulls) if err != nil { return nil, resp, err } return pulls, resp, nil } // Get a single pull request. // // GitHub API docs: https://developer.github.com/v3/pulls/#get-a-single-pull-request func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string, number int) (*PullRequest, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview, mediaTypeDraftPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) pull := new(PullRequest) resp, err := s.client.Do(ctx, req, pull) if err != nil { return nil, resp, err } return pull, resp, nil } // GetRaw gets a single pull request in raw (diff or patch) format. func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo string, number int, opt RawOptions) (string, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return "", nil, err } switch opt.Type { case Diff: req.Header.Set("Accept", mediaTypeV3Diff) case Patch: req.Header.Set("Accept", mediaTypeV3Patch) default: return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type) } var buf bytes.Buffer resp, err := s.client.Do(ctx, req, &buf) if err != nil { return "", resp, err } return buf.String(), resp, nil } // NewPullRequest represents a new pull request to be created. type NewPullRequest struct { Title *string `json:"title,omitempty"` Head *string `json:"head,omitempty"` Base *string `json:"base,omitempty"` Body *string `json:"body,omitempty"` Issue *int `json:"issue,omitempty"` MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` Draft *bool `json:"draft,omitempty"` } // Create a new pull request on the specified repository. // // GitHub API docs: https://developer.github.com/v3/pulls/#create-a-pull-request func (s *PullRequestsService) Create(ctx context.Context, owner string, repo string, pull *NewPullRequest) (*PullRequest, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) req, err := s.client.NewRequest("POST", u, pull) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeDraftPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) p := new(PullRequest) resp, err := s.client.Do(ctx, req, p) if err != nil { return nil, resp, err } return p, resp, nil } // PullReqestBranchUpdateOptions specifies the optional parameters to the // PullRequestsService.UpdateBranch method. type PullReqestBranchUpdateOptions struct { // ExpectedHeadSHA specifies the most recent commit on the pull request's branch. // Default value is the SHA of the pull request's current HEAD ref. ExpectedHeadSHA *string `json:"expected_head_sha,omitempty"` } // PullRequestBranchUpdateResponse specifies the response of pull request branch update. type PullRequestBranchUpdateResponse struct { Message *string `json:"message,omitempty"` URL *string `json:"url,omitempty"` } // UpdateBranch updates the pull request branch with latest upstream changes. // // This method might return an AcceptedError and a status code of // 202. This is because this is the status that GitHub returns to signify that // it has now scheduled the update of the pull request branch in a background task. // A follow up request, after a delay of a second or so, should result // in a successful request. // // GitHub API docs: https://developer.github.com/v3/pulls/#update-a-pull-request-branch func (s *PullRequestsService) UpdateBranch(ctx context.Context, owner, repo string, number int, opts *PullReqestBranchUpdateOptions) (*PullRequestBranchUpdateResponse, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/update-branch", owner, repo, number) req, err := s.client.NewRequest("PUT", u, opts) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeUpdatePullRequestBranchPreview) p := new(PullRequestBranchUpdateResponse) resp, err := s.client.Do(ctx, req, p) if err != nil { return nil, resp, err } return p, resp, nil } type pullRequestUpdate struct { Title *string `json:"title,omitempty"` Body *string `json:"body,omitempty"` State *string `json:"state,omitempty"` Base *string `json:"base,omitempty"` MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` } // Edit a pull request. // pull must not be nil. // // The following fields are editable: Title, Body, State, Base.Ref and MaintainerCanModify. // Base.Ref updates the base branch of the pull request. // // GitHub API docs: https://developer.github.com/v3/pulls/#update-a-pull-request func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo string, number int, pull *PullRequest) (*PullRequest, *Response, error) { if pull == nil { return nil, nil, fmt.Errorf("pull must be provided") } u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) update := &pullRequestUpdate{ Title: pull.Title, Body: pull.Body, State: pull.State, MaintainerCanModify: pull.MaintainerCanModify, } if pull.Base != nil { update.Base = pull.Base.Ref } req, err := s.client.NewRequest("PATCH", u, update) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) p := new(PullRequest) resp, err := s.client.Do(ctx, req, p) if err != nil { return nil, resp, err } return p, resp, nil } // ListCommits lists the commits in a pull request. // // GitHub API docs: https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*RepositoryCommit, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/commits", owner, repo, number) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var commits []*RepositoryCommit resp, err := s.client.Do(ctx, req, &commits) if err != nil { return nil, resp, err } return commits, resp, nil } // ListFiles lists the files in a pull request. // // GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests-files func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*CommitFile, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/files", owner, repo, number) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var commitFiles []*CommitFile resp, err := s.client.Do(ctx, req, &commitFiles) if err != nil { return nil, resp, err } return commitFiles, resp, nil } // IsMerged checks if a pull request has been merged. // // GitHub API docs: https://developer.github.com/v3/pulls/#get-if-a-pull-request-has-been-merged func (s *PullRequestsService) IsMerged(ctx context.Context, owner string, repo string, number int) (bool, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } resp, err := s.client.Do(ctx, req, nil) merged, err := parseBoolResponse(err) return merged, resp, err } // PullRequestMergeResult represents the result of merging a pull request. type PullRequestMergeResult struct { SHA *string `json:"sha,omitempty"` Merged *bool `json:"merged,omitempty"` Message *string `json:"message,omitempty"` } // PullRequestOptions lets you define how a pull request will be merged. type PullRequestOptions struct { CommitTitle string // Extra detail to append to automatic commit message. (Optional.) SHA string // SHA that pull request head must match to allow merge. (Optional.) // The merge method to use. Possible values include: "merge", "squash", and "rebase" with the default being merge. (Optional.) MergeMethod string } type pullRequestMergeRequest struct { CommitMessage string `json:"commit_message"` CommitTitle string `json:"commit_title,omitempty"` MergeMethod string `json:"merge_method,omitempty"` SHA string `json:"sha,omitempty"` } // 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 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) pullRequestBody := &pullRequestMergeRequest{CommitMessage: commitMessage} if options != nil { pullRequestBody.CommitTitle = options.CommitTitle pullRequestBody.MergeMethod = options.MergeMethod pullRequestBody.SHA = options.SHA } req, err := s.client.NewRequest("PUT", u, pullRequestBody) if err != nil { return nil, nil, err } mergeResult := new(PullRequestMergeResult) resp, err := s.client.Do(ctx, req, mergeResult) if err != nil { return nil, resp, err } return mergeResult, resp, nil } go-github-28.1.1/github/pulls_comments.go000066400000000000000000000151471353501270500203560ustar00rootroot00000000000000// 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" "time" ) // PullRequestComment represents a comment left on a pull request. type PullRequestComment struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` InReplyTo *int64 `json:"in_reply_to_id,omitempty"` Body *string `json:"body,omitempty"` Path *string `json:"path,omitempty"` DiffHunk *string `json:"diff_hunk,omitempty"` PullRequestReviewID *int64 `json:"pull_request_review_id,omitempty"` Position *int `json:"position,omitempty"` OriginalPosition *int `json:"original_position,omitempty"` CommitID *string `json:"commit_id,omitempty"` OriginalCommitID *string `json:"original_commit_id,omitempty"` User *User `json:"user,omitempty"` Reactions *Reactions `json:"reactions,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` // AuthorAssociation is the comment author's relationship to the pull request's repository. // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". AuthorAssociation *string `json:"author_association,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` PullRequestURL *string `json:"pull_request_url,omitempty"` } func (p PullRequestComment) String() string { return Stringify(p) } // PullRequestListCommentsOptions specifies the optional parameters to the // PullRequestsService.ListComments method. type PullRequestListCommentsOptions struct { // Sort specifies how to sort comments. Possible values are: created, updated. Sort string `url:"sort,omitempty"` // Direction in which to sort comments. Possible values are: asc, desc. Direction string `url:"direction,omitempty"` // Since filters comments by time. Since time.Time `url:"since,omitempty"` ListOptions } // ListComments lists all comments on the specified pull request. Specifying a // 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 func (s *PullRequestsService) ListComments(ctx context.Context, owner string, repo string, number int, opt *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) { var u string if number == 0 { u = fmt.Sprintf("repos/%v/%v/pulls/comments", owner, repo) } else { u = fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeReactionsPreview) var comments []*PullRequestComment resp, err := s.client.Do(ctx, req, &comments) if err != nil { return nil, resp, err } return comments, resp, nil } // GetComment fetches the specified pull request comment. // // GitHub API docs: https://developer.github.com/v3/pulls/comments/#get-a-single-comment func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*PullRequestComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeReactionsPreview) comment := new(PullRequestComment) resp, err := s.client.Do(ctx, req, comment) if err != nil { return nil, resp, err } return comment, resp, nil } // CreateComment creates a new comment on the specified pull request. // // GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-comment func (s *PullRequestsService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) req, err := s.client.NewRequest("POST", u, comment) if err != nil { return nil, nil, err } c := new(PullRequestComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // 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 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"` InReplyTo int64 `json:"in_reply_to,omitempty"` }{ Body: body, InReplyTo: commentID, } u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) req, err := s.client.NewRequest("POST", u, comment) if err != nil { return nil, nil, err } c := new(PullRequestComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // EditComment updates a pull request comment. // A non-nil comment.Body must be provided. Other comment fields should be left nil. // // GitHub API docs: https://developer.github.com/v3/pulls/comments/#edit-a-comment func (s *PullRequestsService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("PATCH", u, comment) if err != nil { return nil, nil, err } c := new(PullRequestComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // DeleteComment deletes a pull request comment. // // GitHub API docs: https://developer.github.com/v3/pulls/comments/#delete-a-comment func (s *PullRequestsService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/pulls_comments_test.go000066400000000000000000000205371353501270500214140ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" "time" ) func TestPullComments_marshall(t *testing.T) { testJSONMarshal(t, &PullRequestComment{}, "{}") createdAt := time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC) updatedAt := time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC) reactions := &Reactions{ TotalCount: Int(1), PlusOne: Int(1), MinusOne: Int(0), Laugh: Int(0), Confused: Int(0), Heart: Int(0), Hooray: Int(0), URL: String("u"), } u := &PullRequestComment{ ID: Int64(10), InReplyTo: Int64(8), Body: String("Test comment"), Path: String("file1.txt"), DiffHunk: String("@@ -16,33 +16,40 @@ fmt.Println()"), PullRequestReviewID: Int64(42), Position: Int(1), OriginalPosition: Int(4), CommitID: String("ab"), OriginalCommitID: String("9c"), User: &User{ Login: String("ll"), ID: Int64(123), AvatarURL: String("a"), GravatarID: String("g"), Name: String("n"), Company: String("c"), Blog: String("b"), Location: String("l"), Email: String("e"), Hireable: Bool(true), PublicRepos: Int(1), Followers: Int(1), Following: Int(1), CreatedAt: &Timestamp{referenceTime}, URL: String("u"), }, Reactions: reactions, CreatedAt: &createdAt, UpdatedAt: &updatedAt, URL: String("pullrequestcommentUrl"), HTMLURL: String("pullrequestcommentHTMLUrl"), PullRequestURL: String("pullrequestcommentPullRequestURL"), } want := `{ "id": 10, "in_reply_to_id": 8, "body": "Test comment", "path": "file1.txt", "diff_hunk": "@@ -16,33 +16,40 @@ fmt.Println()", "pull_request_review_id": 42, "position": 1, "original_position": 4, "commit_id": "ab", "original_commit_id": "9c", "user": { "login": "ll", "id": 123, "avatar_url": "a", "gravatar_id": "g", "name": "n", "company": "c", "blog": "b", "location": "l", "email": "e", "hireable": true, "public_repos": 1, "followers": 1, "following": 1, "created_at": ` + referenceTimeStr + `, "url": "u" }, "reactions": { "total_count": 1, "+1": 1, "-1": 0, "laugh": 0, "confused": 0, "heart": 0, "hooray": 0, "url": "u" }, "created_at": "2002-02-10T15:30:00Z", "updated_at": "2002-02-10T15:30:00Z", "url": "pullrequestcommentUrl", "html_url": "pullrequestcommentHTMLUrl", "pull_request_url": "pullrequestcommentPullRequestURL" }` testJSONMarshal(t, u, want) } func TestPullRequestsService_ListComments_allPulls(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/comments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) testFormValues(t, r, values{ "sort": "updated", "direction": "desc", "since": "2002-02-10T15:30:00Z", "page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) opt := &PullRequestListCommentsOptions{ Sort: "updated", Direction: "desc", Since: time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC), ListOptions: ListOptions{Page: 2}, } pulls, _, err := client.PullRequests.ListComments(context.Background(), "o", "r", 0, opt) if err != nil { t.Errorf("PullRequests.ListComments returned error: %v", err) } want := []*PullRequestComment{{ID: Int64(1)}} if !reflect.DeepEqual(pulls, want) { t.Errorf("PullRequests.ListComments returned %+v, want %+v", pulls, want) } } func TestPullRequestsService_ListComments_specificPull(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/comments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) fmt.Fprint(w, `[{"id":1, "pull_request_review_id":42}]`) }) pulls, _, err := client.PullRequests.ListComments(context.Background(), "o", "r", 1, nil) if err != nil { t.Errorf("PullRequests.ListComments returned error: %v", err) } want := []*PullRequestComment{{ID: Int64(1), PullRequestReviewID: Int64(42)}} if !reflect.DeepEqual(pulls, want) { t.Errorf("PullRequests.ListComments returned %+v, want %+v", pulls, want) } } func TestPullRequestsService_ListComments_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.ListComments(context.Background(), "%", "r", 1, nil) testURLParseError(t, err) } func TestPullRequestsService_GetComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/comments/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) fmt.Fprint(w, `{"id":1}`) }) comment, _, err := client.PullRequests.GetComment(context.Background(), "o", "r", 1) if err != nil { t.Errorf("PullRequests.GetComment returned error: %v", err) } want := &PullRequestComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("PullRequests.GetComment returned %+v, want %+v", comment, want) } } func TestPullRequestsService_GetComment_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.GetComment(context.Background(), "%", "r", 1) testURLParseError(t, err) } func TestPullRequestsService_CreateComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &PullRequestComment{Body: String("b")} mux.HandleFunc("/repos/o/r/pulls/1/comments", func(w http.ResponseWriter, r *http.Request) { v := new(PullRequestComment) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) comment, _, err := client.PullRequests.CreateComment(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("PullRequests.CreateComment returned error: %v", err) } want := &PullRequestComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("PullRequests.CreateComment returned %+v, want %+v", comment, want) } } func TestPullRequestsService_CreateComment_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.CreateComment(context.Background(), "%", "r", 1, nil) testURLParseError(t, err) } func TestPullRequestsService_EditComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &PullRequestComment{Body: String("b")} mux.HandleFunc("/repos/o/r/pulls/comments/1", func(w http.ResponseWriter, r *http.Request) { v := new(PullRequestComment) 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}`) }) comment, _, err := client.PullRequests.EditComment(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("PullRequests.EditComment returned error: %v", err) } want := &PullRequestComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("PullRequests.EditComment returned %+v, want %+v", comment, want) } } func TestPullRequestsService_EditComment_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.EditComment(context.Background(), "%", "r", 1, nil) testURLParseError(t, err) } func TestPullRequestsService_DeleteComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/comments/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.PullRequests.DeleteComment(context.Background(), "o", "r", 1) if err != nil { t.Errorf("PullRequests.DeleteComment returned error: %v", err) } } func TestPullRequestsService_DeleteComment_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.PullRequests.DeleteComment(context.Background(), "%", "r", 1) testURLParseError(t, err) } go-github-28.1.1/github/pulls_reviewers.go000066400000000000000000000051371353501270500205420ustar00rootroot00000000000000// Copyright 2017 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" ) // ReviewersRequest specifies users and teams for a pull request review request. type ReviewersRequest struct { NodeID *string `json:"node_id,omitempty"` Reviewers []string `json:"reviewers,omitempty"` TeamReviewers []string `json:"team_reviewers,omitempty"` } // Reviewers represents reviewers of a pull request. type Reviewers struct { Users []*User `json:"users,omitempty"` Teams []*Team `json:"teams,omitempty"` } // RequestReviewers creates a review request for the provided reviewers for the specified pull request. // // GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#create-a-review-request func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*PullRequest, *Response, error) { u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) req, err := s.client.NewRequest("POST", u, &reviewers) if err != nil { return nil, nil, err } r := new(PullRequest) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // ListReviewers lists reviewers whose reviews have been requested on the specified pull request. // // GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#list-review-requests func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo string, number int, opt *ListOptions) (*Reviewers, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/requested_reviewers", owner, repo, number) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } reviewers := new(Reviewers) resp, err := s.client.Do(ctx, req, reviewers) if err != nil { return nil, resp, err } return reviewers, resp, nil } // RemoveReviewers removes the review request for the provided reviewers for the specified pull request. // // GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#delete-a-review-request func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*Response, error) { u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) req, err := s.client.NewRequest("DELETE", u, &reviewers) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/pulls_reviewers_test.go000066400000000000000000000136671353501270500216100ustar00rootroot00000000000000// Copyright 2017 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" "reflect" "testing" "time" ) func TestRequestReviewers(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/requested_reviewers", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testBody(t, r, `{"reviewers":["octocat","googlebot"],"team_reviewers":["justice-league","injustice-league"]}`+"\n") fmt.Fprint(w, `{"number":1}`) }) // This returns a PR, unmarshalling of which is tested elsewhere ctx := context.Background() got, _, err := client.PullRequests.RequestReviewers(ctx, "o", "r", 1, ReviewersRequest{Reviewers: []string{"octocat", "googlebot"}, TeamReviewers: []string{"justice-league", "injustice-league"}}) if err != nil { t.Errorf("PullRequests.RequestReviewers returned error: %v", err) } want := &PullRequest{Number: Int(1)} if !reflect.DeepEqual(got, want) { t.Errorf("PullRequests.RequestReviewers returned %+v, want %+v", got, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.PullRequests.RequestReviewers(ctx, "o", "r", 1, ReviewersRequest{Reviewers: []string{"octocat", "googlebot"}, TeamReviewers: []string{"justice-league", "injustice-league"}}) if got != nil { t.Errorf("client.BaseURL.Path='' RequestReviewers = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' RequestReviewers resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' RequestReviewers err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.PullRequests.RequestReviewers(ctx, "o", "r", 1, ReviewersRequest{Reviewers: []string{"octocat", "googlebot"}, TeamReviewers: []string{"justice-league", "injustice-league"}}) if got != nil { t.Errorf("rate.Reset.Time > now RequestReviewers = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now RequestReviewers resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now RequestReviewers err = nil, want error") } } func TestRemoveReviewers(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/requested_reviewers", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testBody(t, r, `{"reviewers":["octocat","googlebot"],"team_reviewers":["justice-league"]}`+"\n") }) ctx := context.Background() _, err := client.PullRequests.RemoveReviewers(ctx, "o", "r", 1, ReviewersRequest{Reviewers: []string{"octocat", "googlebot"}, TeamReviewers: []string{"justice-league"}}) if err != nil { t.Errorf("PullRequests.RemoveReviewers returned error: %v", err) } // Test s.client.NewRequest failure client.BaseURL.Path = "" resp, err := client.PullRequests.RemoveReviewers(ctx, "o", "r", 1, ReviewersRequest{Reviewers: []string{"octocat", "googlebot"}, TeamReviewers: []string{"justice-league"}}) if resp != nil { t.Errorf("client.BaseURL.Path='' RemoveReviewers resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' RemoveReviewers err = nil, want error") } } func TestListReviewers(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/requested_reviewers", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"users":[{"login":"octocat","id":1}],"teams":[{"id":1,"name":"Justice League"}]}`) }) ctx := context.Background() got, _, err := client.PullRequests.ListReviewers(ctx, "o", "r", 1, nil) if err != nil { t.Errorf("PullRequests.ListReviewers returned error: %v", err) } want := &Reviewers{ Users: []*User{ { Login: String("octocat"), ID: Int64(1), }, }, Teams: []*Team{ { ID: Int64(1), Name: String("Justice League"), }, }, } if !reflect.DeepEqual(got, want) { t.Errorf("PullRequests.ListReviewers returned %+v, want %+v", got, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.PullRequests.ListReviewers(ctx, "o", "r", 1, nil) if got != nil { t.Errorf("client.BaseURL.Path='' ListReviewers = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' ListReviewers resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' ListReviewers err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.PullRequests.ListReviewers(ctx, "o", "r", 1, nil) if got != nil { t.Errorf("rate.Reset.Time > now ListReviewers = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now ListReviewers resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now ListReviewers err = nil, want error") } } func TestListReviewers_withOptions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/requested_reviewers", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `{}`) }) _, _, err := client.PullRequests.ListReviewers(context.Background(), "o", "r", 1, &ListOptions{Page: 2}) if err != nil { t.Errorf("PullRequests.ListReviewers returned error: %v", err) } // Test addOptions failure _, _, err = client.PullRequests.ListReviewers(context.Background(), "\n", "\n", 1, &ListOptions{Page: 2}) if err == nil { t.Error("bad options ListReviewers err = nil, want error") } } go-github-28.1.1/github/pulls_reviews.go000066400000000000000000000214121353501270500202050ustar00rootroot00000000000000// Copyright 2016 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "time" ) // PullRequestReview represents a review of a pull request. type PullRequestReview struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` User *User `json:"user,omitempty"` Body *string `json:"body,omitempty"` SubmittedAt *time.Time `json:"submitted_at,omitempty"` CommitID *string `json:"commit_id,omitempty"` HTMLURL *string `json:"html_url,omitempty"` PullRequestURL *string `json:"pull_request_url,omitempty"` State *string `json:"state,omitempty"` } func (p PullRequestReview) String() string { return Stringify(p) } // DraftReviewComment represents a comment part of the review. type DraftReviewComment struct { Path *string `json:"path,omitempty"` Position *int `json:"position,omitempty"` Body *string `json:"body,omitempty"` } func (c DraftReviewComment) String() string { return Stringify(c) } // PullRequestReviewRequest represents a request to create a review. type PullRequestReviewRequest struct { NodeID *string `json:"node_id,omitempty"` CommitID *string `json:"commit_id,omitempty"` Body *string `json:"body,omitempty"` Event *string `json:"event,omitempty"` Comments []*DraftReviewComment `json:"comments,omitempty"` } func (r PullRequestReviewRequest) String() string { return Stringify(r) } // PullRequestReviewDismissalRequest represents a request to dismiss a review. type PullRequestReviewDismissalRequest struct { Message *string `json:"message,omitempty"` } func (r PullRequestReviewDismissalRequest) String() string { return Stringify(r) } // ListReviews lists all reviews on the specified pull request. // // TODO: Follow up with GitHub support about an issue with this method's // returned error format and remove this comment once it's fixed. // Read more about it here - https://github.com/google/go-github/issues/540 // // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var reviews []*PullRequestReview resp, err := s.client.Do(ctx, req, &reviews) if err != nil { return nil, resp, err } return reviews, resp, nil } // GetReview fetches the specified pull request review. // // TODO: Follow up with GitHub support about an issue with this method's // returned error format and remove this comment once it's fixed. // Read more about it here - https://github.com/google/go-github/issues/540 // // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-a-single-review func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } review := new(PullRequestReview) resp, err := s.client.Do(ctx, req, review) if err != nil { return nil, resp, err } return review, resp, nil } // DeletePendingReview deletes the specified pull request pending review. // // TODO: Follow up with GitHub support about an issue with this method's // returned error format and remove this comment once it's fixed. // Read more about it here - https://github.com/google/go-github/issues/540 // // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, nil, err } review := new(PullRequestReview) resp, err := s.client.Do(ctx, req, review) if err != nil { return nil, resp, err } return review, resp, nil } // ListReviewComments lists all the comments for the specified review. // // TODO: Follow up with GitHub support about an issue with this method's // returned error format and remove this comment once it's fixed. // Read more about it here - https://github.com/google/go-github/issues/540 // // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opt *ListOptions) ([]*PullRequestComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var comments []*PullRequestComment resp, err := s.client.Do(ctx, req, &comments) if err != nil { return nil, resp, err } return comments, resp, nil } // CreateReview creates a new review on the specified pull request. // // TODO: Follow up with GitHub support about an issue with this method's // returned error format and remove this comment once it's fixed. // Read more about it here - https://github.com/google/go-github/issues/540 // // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) req, err := s.client.NewRequest("POST", u, review) if err != nil { return nil, nil, err } r := new(PullRequestReview) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // UpdateReview updates the review summary on the specified pull request. // // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#update-a-pull-request-review func (s *PullRequestsService) UpdateReview(ctx context.Context, owner, repo string, number int, reviewID int64, body string) (*PullRequestReview, *Response, error) { opts := &struct { Body string `json:"body"` }{Body: body} u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) req, err := s.client.NewRequest("PUT", u, opts) if err != nil { return nil, nil, err } review := &PullRequestReview{} resp, err := s.client.Do(ctx, req, review) if err != nil { return nil, resp, err } return review, resp, nil } // SubmitReview submits a specified review on the specified pull request. // // TODO: Follow up with GitHub support about an issue with this method's // returned error format and remove this comment once it's fixed. // Read more about it here - https://github.com/google/go-github/issues/540 // // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID) req, err := s.client.NewRequest("POST", u, review) if err != nil { return nil, nil, err } r := new(PullRequestReview) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // DismissReview dismisses a specified review on the specified pull request. // // TODO: Follow up with GitHub support about an issue with this method's // returned error format and remove this comment once it's fixed. // Read more about it here - https://github.com/google/go-github/issues/540 // // GitHub API docs: https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID) req, err := s.client.NewRequest("PUT", u, review) if err != nil { return nil, nil, err } r := new(PullRequestReview) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } go-github-28.1.1/github/pulls_reviews_test.go000066400000000000000000000205331353501270500212470ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestPullRequestsService_ListReviews(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/reviews", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[{"id":1},{"id":2}]`) }) opt := &ListOptions{Page: 2} reviews, _, err := client.PullRequests.ListReviews(context.Background(), "o", "r", 1, opt) if err != nil { t.Errorf("PullRequests.ListReviews returned error: %v", err) } want := []*PullRequestReview{ {ID: Int64(1)}, {ID: Int64(2)}, } if !reflect.DeepEqual(reviews, want) { t.Errorf("PullRequests.ListReviews returned %+v, want %+v", reviews, want) } } func TestPullRequestsService_ListReviews_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.ListReviews(context.Background(), "%", "r", 1, nil) testURLParseError(t, err) } func TestPullRequestsService_GetReview(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) review, _, err := client.PullRequests.GetReview(context.Background(), "o", "r", 1, 1) if err != nil { t.Errorf("PullRequests.GetReview returned error: %v", err) } want := &PullRequestReview{ID: Int64(1)} if !reflect.DeepEqual(review, want) { t.Errorf("PullRequests.GetReview returned %+v, want %+v", review, want) } } func TestPullRequestsService_GetReview_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.GetReview(context.Background(), "%", "r", 1, 1) testURLParseError(t, err) } func TestPullRequestsService_DeletePendingReview(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") fmt.Fprint(w, `{"id":1}`) }) review, _, err := client.PullRequests.DeletePendingReview(context.Background(), "o", "r", 1, 1) if err != nil { t.Errorf("PullRequests.DeletePendingReview returned error: %v", err) } want := &PullRequestReview{ID: Int64(1)} if !reflect.DeepEqual(review, want) { t.Errorf("PullRequests.DeletePendingReview returned %+v, want %+v", review, want) } } func TestPullRequestsService_DeletePendingReview_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.DeletePendingReview(context.Background(), "%", "r", 1, 1) testURLParseError(t, err) } func TestPullRequestsService_ListReviewComments(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/comments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1},{"id":2}]`) }) comments, _, err := client.PullRequests.ListReviewComments(context.Background(), "o", "r", 1, 1, nil) if err != nil { t.Errorf("PullRequests.ListReviewComments returned error: %v", err) } want := []*PullRequestComment{ {ID: Int64(1)}, {ID: Int64(2)}, } if !reflect.DeepEqual(comments, want) { t.Errorf("PullRequests.ListReviewComments returned %+v, want %+v", comments, want) } } func TestPullRequestsService_ListReviewComments_withOptions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/comments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[]`) }) _, _, err := client.PullRequests.ListReviewComments(context.Background(), "o", "r", 1, 1, &ListOptions{Page: 2}) if err != nil { t.Errorf("PullRequests.ListReviewComments returned error: %v", err) } } func TestPullRequestsService_ListReviewComments_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.ListReviewComments(context.Background(), "%", "r", 1, 1, nil) testURLParseError(t, err) } func TestPullRequestsService_CreateReview(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &PullRequestReviewRequest{ CommitID: String("commit_id"), Body: String("b"), Event: String("APPROVE"), } mux.HandleFunc("/repos/o/r/pulls/1/reviews", func(w http.ResponseWriter, r *http.Request) { v := new(PullRequestReviewRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) review, _, err := client.PullRequests.CreateReview(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("PullRequests.CreateReview returned error: %v", err) } want := &PullRequestReview{ID: Int64(1)} if !reflect.DeepEqual(review, want) { t.Errorf("PullRequests.CreateReview returned %+v, want %+v", review, want) } } func TestPullRequestsService_CreateReview_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.CreateReview(context.Background(), "%", "r", 1, &PullRequestReviewRequest{}) testURLParseError(t, err) } func TestPullRequestsService_UpdateReview(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") fmt.Fprintf(w, `{"id":1}`) }) got, _, err := client.PullRequests.UpdateReview(context.Background(), "o", "r", 1, 1, "updated_body") if err != nil { t.Errorf("PullRequests.UpdateReview returned error: %v", err) } want := &PullRequestReview{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("PullRequests.UpdateReview = %+v, want %+v", got, want) } } func TestPullRequestsService_SubmitReview(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &PullRequestReviewRequest{ Body: String("b"), Event: String("APPROVE"), } mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/events", func(w http.ResponseWriter, r *http.Request) { v := new(PullRequestReviewRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) review, _, err := client.PullRequests.SubmitReview(context.Background(), "o", "r", 1, 1, input) if err != nil { t.Errorf("PullRequests.SubmitReview returned error: %v", err) } want := &PullRequestReview{ID: Int64(1)} if !reflect.DeepEqual(review, want) { t.Errorf("PullRequests.SubmitReview returned %+v, want %+v", review, want) } } func TestPullRequestsService_SubmitReview_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.SubmitReview(context.Background(), "%", "r", 1, 1, &PullRequestReviewRequest{}) testURLParseError(t, err) } func TestPullRequestsService_DismissReview(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &PullRequestReviewDismissalRequest{Message: String("m")} mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/dismissals", func(w http.ResponseWriter, r *http.Request) { v := new(PullRequestReviewDismissalRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) review, _, err := client.PullRequests.DismissReview(context.Background(), "o", "r", 1, 1, input) if err != nil { t.Errorf("PullRequests.DismissReview returned error: %v", err) } want := &PullRequestReview{ID: Int64(1)} if !reflect.DeepEqual(review, want) { t.Errorf("PullRequests.DismissReview returned %+v, want %+v", review, want) } } func TestPullRequestsService_DismissReview_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.DismissReview(context.Background(), "%", "r", 1, 1, &PullRequestReviewDismissalRequest{}) testURLParseError(t, err) } go-github-28.1.1/github/pulls_test.go000066400000000000000000000500451353501270500175040ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "io" "net/http" "reflect" "strings" "testing" ) func TestPullRequestsService_List(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview, mediaTypeDraftPreview} mux.HandleFunc("/repos/o/r/pulls", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{ "state": "closed", "head": "h", "base": "b", "sort": "created", "direction": "desc", "page": "2", }) fmt.Fprint(w, `[{"number":1}]`) }) opt := &PullRequestListOptions{"closed", "h", "b", "created", "desc", ListOptions{Page: 2}} pulls, _, err := client.PullRequests.List(context.Background(), "o", "r", opt) if err != nil { t.Errorf("PullRequests.List returned error: %v", err) } want := []*PullRequest{{Number: Int(1)}} if !reflect.DeepEqual(pulls, want) { t.Errorf("PullRequests.List returned %+v, want %+v", pulls, want) } } func TestPullRequestsService_ListPullRequestsWithCommit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeListPullsOrBranchesForCommitPreview, mediaTypeDraftPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} mux.HandleFunc("/repos/o/r/commits/sha/pulls", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{ "state": "closed", "head": "h", "base": "b", "sort": "created", "direction": "desc", "page": "2", }) fmt.Fprint(w, `[{"number":1}]`) }) opt := &PullRequestListOptions{"closed", "h", "b", "created", "desc", ListOptions{Page: 2}} pulls, _, err := client.PullRequests.ListPullRequestsWithCommit(context.Background(), "o", "r", "sha", opt) if err != nil { t.Errorf("PullRequests.ListPullRequestsWithCommit returned error: %v", err) } want := []*PullRequest{{Number: Int(1)}} if !reflect.DeepEqual(pulls, want) { t.Errorf("PullRequests.ListPullRequestsWithCommit returned %+v, want %+v", pulls, want) } } func TestPullRequestsService_List_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.List(context.Background(), "%", "r", nil) testURLParseError(t, err) } func TestPullRequestsService_Get(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview, mediaTypeDraftPreview} mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `{"number":1}`) }) pull, _, err := client.PullRequests.Get(context.Background(), "o", "r", 1) if err != nil { t.Errorf("PullRequests.Get returned error: %v", err) } want := &PullRequest{Number: Int(1)} if !reflect.DeepEqual(pull, want) { t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want) } } func TestPullRequestsService_GetRaw_diff(t *testing.T) { client, mux, _, teardown := setup() defer teardown() const rawStr = "@@diff content" mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeV3Diff) fmt.Fprint(w, rawStr) }) got, _, err := client.PullRequests.GetRaw(context.Background(), "o", "r", 1, RawOptions{Diff}) if err != nil { t.Fatalf("PullRequests.GetRaw returned error: %v", err) } want := rawStr if got != want { t.Errorf("PullRequests.GetRaw returned %s want %s", got, want) } } func TestPullRequestsService_GetRaw_patch(t *testing.T) { client, mux, _, teardown := setup() defer teardown() const rawStr = "@@patch content" mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeV3Patch) fmt.Fprint(w, rawStr) }) got, _, err := client.PullRequests.GetRaw(context.Background(), "o", "r", 1, RawOptions{Patch}) if err != nil { t.Fatalf("PullRequests.GetRaw returned error: %v", err) } want := rawStr if got != want { t.Errorf("PullRequests.GetRaw returned %s want %s", got, want) } } func TestPullRequestsService_GetRaw_invalid(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.GetRaw(context.Background(), "o", "r", 1, RawOptions{100}) if err == nil { t.Fatal("PullRequests.GetRaw should return error") } if !strings.Contains(err.Error(), "unsupported raw type") { t.Error("PullRequests.GetRaw should return unsupported raw type error") } } func TestPullRequestsService_Get_links(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{ "number":1, "_links":{ "self":{"href":"https://api.github.com/repos/octocat/Hello-World/pulls/1347"}, "html":{"href":"https://github.com/octocat/Hello-World/pull/1347"}, "issue":{"href":"https://api.github.com/repos/octocat/Hello-World/issues/1347"}, "comments":{"href":"https://api.github.com/repos/octocat/Hello-World/issues/1347/comments"}, "review_comments":{"href":"https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments"}, "review_comment":{"href":"https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}"}, "commits":{"href":"https://api.github.com/repos/octocat/Hello-World/pulls/1347/commits"}, "statuses":{"href":"https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e"} } }`) }) pull, _, err := client.PullRequests.Get(context.Background(), "o", "r", 1) if err != nil { t.Errorf("PullRequests.Get returned error: %v", err) } want := &PullRequest{ Number: Int(1), Links: &PRLinks{ Self: &PRLink{ HRef: String("https://api.github.com/repos/octocat/Hello-World/pulls/1347"), }, HTML: &PRLink{ HRef: String("https://github.com/octocat/Hello-World/pull/1347"), }, Issue: &PRLink{ HRef: String("https://api.github.com/repos/octocat/Hello-World/issues/1347"), }, Comments: &PRLink{ HRef: String("https://api.github.com/repos/octocat/Hello-World/issues/1347/comments"), }, ReviewComments: &PRLink{ HRef: String("https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments"), }, ReviewComment: &PRLink{ HRef: String("https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}"), }, Commits: &PRLink{ HRef: String("https://api.github.com/repos/octocat/Hello-World/pulls/1347/commits"), }, Statuses: &PRLink{ HRef: String("https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e"), }, }, } if !reflect.DeepEqual(pull, want) { t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want) } } func TestPullRequestsService_Get_headAndBase(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"number":1,"head":{"ref":"r2","repo":{"id":2}},"base":{"ref":"r1","repo":{"id":1}}}`) }) pull, _, err := client.PullRequests.Get(context.Background(), "o", "r", 1) if err != nil { t.Errorf("PullRequests.Get returned error: %v", err) } want := &PullRequest{ Number: Int(1), Head: &PullRequestBranch{ Ref: String("r2"), Repo: &Repository{ID: Int64(2)}, }, Base: &PullRequestBranch{ Ref: String("r1"), Repo: &Repository{ID: Int64(1)}, }, } if !reflect.DeepEqual(pull, want) { t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want) } } func TestPullRequestsService_Get_urlFields(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"number":1, "url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347", "html_url": "https://github.com/octocat/Hello-World/pull/1347", "issue_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347", "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e", "diff_url": "https://github.com/octocat/Hello-World/pull/1347.diff", "patch_url": "https://github.com/octocat/Hello-World/pull/1347.patch", "review_comments_url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments", "review_comment_url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}"}`) }) pull, _, err := client.PullRequests.Get(context.Background(), "o", "r", 1) if err != nil { t.Errorf("PullRequests.Get returned error: %v", err) } want := &PullRequest{ Number: Int(1), URL: String("https://api.github.com/repos/octocat/Hello-World/pulls/1347"), HTMLURL: String("https://github.com/octocat/Hello-World/pull/1347"), IssueURL: String("https://api.github.com/repos/octocat/Hello-World/issues/1347"), StatusesURL: String("https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e"), DiffURL: String("https://github.com/octocat/Hello-World/pull/1347.diff"), PatchURL: String("https://github.com/octocat/Hello-World/pull/1347.patch"), ReviewCommentsURL: String("https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments"), ReviewCommentURL: String("https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}"), } if !reflect.DeepEqual(pull, want) { t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want) } } func TestPullRequestsService_Get_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.Get(context.Background(), "%", "r", 1) testURLParseError(t, err) } func TestPullRequestsService_Create(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &NewPullRequest{Title: String("t")} mux.HandleFunc("/repos/o/r/pulls", func(w http.ResponseWriter, r *http.Request) { v := new(NewPullRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") wantAcceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeDraftPreview} testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"number":1}`) }) pull, _, err := client.PullRequests.Create(context.Background(), "o", "r", input) if err != nil { t.Errorf("PullRequests.Create returned error: %v", err) } want := &PullRequest{Number: Int(1)} if !reflect.DeepEqual(pull, want) { t.Errorf("PullRequests.Create returned %+v, want %+v", pull, want) } } func TestPullRequestsService_Create_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.Create(context.Background(), "%", "r", nil) testURLParseError(t, err) } func TestPullRequestsService_UpdateBranch(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/update-branch", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeUpdatePullRequestBranchPreview) fmt.Fprint(w, ` { "message": "Updating pull request branch.", "url": "https://github.com/repos/o/r/pulls/1" }`) }) opts := &PullReqestBranchUpdateOptions{ ExpectedHeadSHA: String("s"), } pull, _, err := client.PullRequests.UpdateBranch(context.Background(), "o", "r", 1, opts) if err != nil { t.Errorf("PullRequests.UpdateBranch returned error: %v", err) } want := &PullRequestBranchUpdateResponse{ Message: String("Updating pull request branch."), URL: String("https://github.com/repos/o/r/pulls/1"), } if !reflect.DeepEqual(pull, want) { t.Errorf("PullRequests.UpdateBranch returned %+v, want %+v", pull, want) } } func TestPullRequestsService_Edit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() tests := []struct { input *PullRequest sendResponse string wantUpdate string want *PullRequest }{ { input: &PullRequest{Title: String("t")}, sendResponse: `{"number":1}`, wantUpdate: `{"title":"t"}`, want: &PullRequest{Number: Int(1)}, }, { // base update input: &PullRequest{Base: &PullRequestBranch{Ref: String("master")}}, sendResponse: `{"number":1,"base":{"ref":"master"}}`, wantUpdate: `{"base":"master"}`, want: &PullRequest{ Number: Int(1), Base: &PullRequestBranch{Ref: String("master")}, }, }, } for i, tt := range tests { madeRequest := false wantAcceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} mux.HandleFunc(fmt.Sprintf("/repos/o/r/pulls/%v", i), func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testBody(t, r, tt.wantUpdate+"\n") io.WriteString(w, tt.sendResponse) madeRequest = true }) pull, _, err := client.PullRequests.Edit(context.Background(), "o", "r", i, tt.input) if err != nil { t.Errorf("%d: PullRequests.Edit returned error: %v", i, err) } if !reflect.DeepEqual(pull, tt.want) { t.Errorf("%d: PullRequests.Edit returned %+v, want %+v", i, pull, tt.want) } if !madeRequest { t.Errorf("%d: PullRequest.Edit did not make the expected request", i) } } } func TestPullRequestsService_Edit_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.PullRequests.Edit(context.Background(), "%", "r", 1, &PullRequest{}) testURLParseError(t, err) } func TestPullRequestsService_ListCommits(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/commits", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, ` [ { "sha": "3", "parents": [ { "sha": "2" } ] }, { "sha": "2", "parents": [ { "sha": "1" } ] } ]`) }) opt := &ListOptions{Page: 2} commits, _, err := client.PullRequests.ListCommits(context.Background(), "o", "r", 1, opt) if err != nil { t.Errorf("PullRequests.ListCommits returned error: %v", err) } want := []*RepositoryCommit{ { SHA: String("3"), Parents: []Commit{ { SHA: String("2"), }, }, }, { SHA: String("2"), Parents: []Commit{ { SHA: String("1"), }, }, }, } if !reflect.DeepEqual(commits, want) { t.Errorf("PullRequests.ListCommits returned %+v, want %+v", commits, want) } } func TestPullRequestsService_ListFiles(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/files", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, ` [ { "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", "filename": "file1.txt", "status": "added", "additions": 103, "deletions": 21, "changes": 124, "patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test" }, { "sha": "f61aebed695e2e4193db5e6dcb09b5b57875f334", "filename": "file2.txt", "status": "modified", "additions": 5, "deletions": 3, "changes": 103, "patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test" } ]`) }) opt := &ListOptions{Page: 2} commitFiles, _, err := client.PullRequests.ListFiles(context.Background(), "o", "r", 1, opt) if err != nil { t.Errorf("PullRequests.ListFiles returned error: %v", err) } want := []*CommitFile{ { SHA: String("6dcb09b5b57875f334f61aebed695e2e4193db5e"), Filename: String("file1.txt"), Additions: Int(103), Deletions: Int(21), Changes: Int(124), Status: String("added"), Patch: String("@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"), }, { SHA: String("f61aebed695e2e4193db5e6dcb09b5b57875f334"), Filename: String("file2.txt"), Additions: Int(5), Deletions: Int(3), Changes: Int(103), Status: String("modified"), Patch: String("@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"), }, } if !reflect.DeepEqual(commitFiles, want) { t.Errorf("PullRequests.ListFiles returned %+v, want %+v", commitFiles, want) } } func TestPullRequestsService_IsMerged(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/merge", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNoContent) }) isMerged, _, err := client.PullRequests.IsMerged(context.Background(), "o", "r", 1) if err != nil { t.Errorf("PullRequests.IsMerged returned error: %v", err) } want := true if !reflect.DeepEqual(isMerged, want) { t.Errorf("PullRequests.IsMerged returned %+v, want %+v", isMerged, want) } } func TestPullRequestsService_Merge(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/1/merge", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") fmt.Fprint(w, ` { "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", "merged": true, "message": "Pull Request successfully merged" }`) }) options := &PullRequestOptions{MergeMethod: "rebase"} merge, _, err := client.PullRequests.Merge(context.Background(), "o", "r", 1, "merging pull request", options) if err != nil { t.Errorf("PullRequests.Merge returned error: %v", err) } want := &PullRequestMergeResult{ SHA: String("6dcb09b5b57875f334f61aebed695e2e4193db5e"), Merged: Bool(true), Message: String("Pull Request successfully merged"), } if !reflect.DeepEqual(merge, want) { t.Errorf("PullRequests.Merge returned %+v, want %+v", merge, want) } } // Test that different merge options produce expected PUT requests. See issue https://github.com/google/go-github/issues/500. func TestPullRequestsService_Merge_options(t *testing.T) { client, mux, _, teardown := setup() defer teardown() tests := []struct { options *PullRequestOptions wantBody string }{ { options: nil, wantBody: `{"commit_message":"merging pull request"}`, }, { options: &PullRequestOptions{}, wantBody: `{"commit_message":"merging pull request"}`, }, { options: &PullRequestOptions{MergeMethod: "rebase"}, wantBody: `{"commit_message":"merging pull request","merge_method":"rebase"}`, }, { options: &PullRequestOptions{SHA: "6dcb09b5b57875f334f61aebed695e2e4193db5e"}, wantBody: `{"commit_message":"merging pull request","sha":"6dcb09b5b57875f334f61aebed695e2e4193db5e"}`, }, { options: &PullRequestOptions{ CommitTitle: "Extra detail", SHA: "6dcb09b5b57875f334f61aebed695e2e4193db5e", MergeMethod: "squash", }, wantBody: `{"commit_message":"merging pull request","commit_title":"Extra detail","merge_method":"squash","sha":"6dcb09b5b57875f334f61aebed695e2e4193db5e"}`, }, } for i, test := range tests { madeRequest := false mux.HandleFunc(fmt.Sprintf("/repos/o/r/pulls/%d/merge", i), func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testBody(t, r, test.wantBody+"\n") madeRequest = true }) _, _, _ = client.PullRequests.Merge(context.Background(), "o", "r", i, "merging pull request", test.options) if !madeRequest { t.Errorf("%d: PullRequests.Merge(%#v): expected request was not made", i, test.options) } } } go-github-28.1.1/github/reactions.go000066400000000000000000000304271353501270500172770ustar00rootroot00000000000000// 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" ) // ReactionsService provides access to the reactions-related functions in the // GitHub API. // // GitHub API docs: https://developer.github.com/v3/reactions/ 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) } // 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, opt *ListOptions) ([]*Reaction, *Response, error) { u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept 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 } // 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, opt *ListOptions) ([]*Reaction, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept 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 } // 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, opt *ListOptions) ([]*Reaction, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept 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 } // 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, opt *ListOptions) ([]*Reaction, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept 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 } // 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, opt *ListOptions) ([]*Reaction, *Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", 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 } // 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, opt *ListOptions) ([]*Reaction, *Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", 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 } // DeleteReaction deletes a reaction. // // GitHub API docs: https://developer.github.com/v3/reaction/reactions/#delete-a-reaction-archive func (s *ReactionsService) DeleteReaction(ctx context.Context, id int64) (*Response, error) { u := fmt.Sprintf("reactions/%v", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeReactionsPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/reactions_test.go000066400000000000000000000245251353501270500203400ustar00rootroot00000000000000// 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" "net/http" "reflect" "testing" ) func TestReactionsService_ListCommentReactions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusOK) w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`)) }) got, _, err := client.Reactions.ListCommentReactions(context.Background(), "o", "r", 1, nil) if err != nil { t.Errorf("ListCommentReactions returned error: %v", err) } want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}} if !reflect.DeepEqual(got, want) { t.Errorf("ListCommentReactions = %+v, want %+v", got, want) } } func TestReactionsService_CreateCommentReaction(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusCreated) w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`)) }) got, _, err := client.Reactions.CreateCommentReaction(context.Background(), "o", "r", 1, "+1") if err != nil { t.Errorf("CreateCommentReaction returned error: %v", err) } want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")} if !reflect.DeepEqual(got, want) { t.Errorf("CreateCommentReaction = %+v, want %+v", got, want) } } func TestReactionsService_ListIssueReactions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusOK) w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`)) }) got, _, err := client.Reactions.ListIssueReactions(context.Background(), "o", "r", 1, nil) if err != nil { t.Errorf("ListIssueReactions returned error: %v", err) } want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}} if !reflect.DeepEqual(got, want) { t.Errorf("ListIssueReactions = %+v, want %+v", got, want) } } func TestReactionsService_CreateIssueReaction(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/1/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusCreated) w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`)) }) got, _, err := client.Reactions.CreateIssueReaction(context.Background(), "o", "r", 1, "+1") if err != nil { t.Errorf("CreateIssueReaction returned error: %v", err) } want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")} if !reflect.DeepEqual(got, want) { t.Errorf("CreateIssueReaction = %+v, want %+v", got, want) } } func TestReactionsService_ListIssueCommentReactions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusOK) w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`)) }) got, _, err := client.Reactions.ListIssueCommentReactions(context.Background(), "o", "r", 1, nil) if err != nil { t.Errorf("ListIssueCommentReactions returned error: %v", err) } want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}} if !reflect.DeepEqual(got, want) { t.Errorf("ListIssueCommentReactions = %+v, want %+v", got, want) } } func TestReactionsService_CreateIssueCommentReaction(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/issues/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusCreated) w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`)) }) got, _, err := client.Reactions.CreateIssueCommentReaction(context.Background(), "o", "r", 1, "+1") if err != nil { t.Errorf("CreateIssueCommentReaction returned error: %v", err) } want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")} if !reflect.DeepEqual(got, want) { t.Errorf("CreateIssueCommentReaction = %+v, want %+v", got, want) } } func TestReactionsService_ListPullRequestCommentReactions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusOK) w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`)) }) got, _, err := client.Reactions.ListPullRequestCommentReactions(context.Background(), "o", "r", 1, nil) if err != nil { t.Errorf("ListPullRequestCommentReactions returned error: %v", err) } want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}} if !reflect.DeepEqual(got, want) { t.Errorf("ListPullRequestCommentReactions = %+v, want %+v", got, want) } } func TestReactionsService_CreatePullRequestCommentReaction(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pulls/comments/1/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusCreated) w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`)) }) got, _, err := client.Reactions.CreatePullRequestCommentReaction(context.Background(), "o", "r", 1, "+1") if err != nil { t.Errorf("CreatePullRequestCommentReaction returned error: %v", err) } want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")} if !reflect.DeepEqual(got, want) { t.Errorf("CreatePullRequestCommentReaction = %+v, want %+v", got, want) } } func TestReactionsService_ListTeamDiscussionReactions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/discussions/2/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusOK) w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`)) }) got, _, err := client.Reactions.ListTeamDiscussionReactions(context.Background(), 1, 2, nil) if err != nil { t.Errorf("ListTeamDiscussionReactions returned error: %v", err) } want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}} if !reflect.DeepEqual(got, want) { t.Errorf("ListTeamDiscussionReactions = %+v, want %+v", got, want) } } func TestReactionsService_CreateTeamDiscussionReaction(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/discussions/2/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusCreated) w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`)) }) got, _, err := client.Reactions.CreateTeamDiscussionReaction(context.Background(), 1, 2, "+1") if err != nil { t.Errorf("CreateTeamDiscussionReaction returned error: %v", err) } want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")} if !reflect.DeepEqual(got, want) { t.Errorf("CreateTeamDiscussionReaction = %+v, want %+v", got, want) } } func TestReactionService_ListTeamDiscussionCommentReactions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/discussions/2/comments/3/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusOK) w.Write([]byte(`[{"id":1,"user":{"login":"l","id":2},"content":"+1"}]`)) }) got, _, err := client.Reactions.ListTeamDiscussionCommentReactions(context.Background(), 1, 2, 3, nil) if err != nil { t.Errorf("ListTeamDiscussionCommentReactions returned error: %v", err) } want := []*Reaction{{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")}} if !reflect.DeepEqual(got, want) { t.Errorf("ListTeamDiscussionCommentReactions = %+v, want %+v", got, want) } } func TestReactionService_CreateTeamDiscussionCommentReaction(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/discussions/2/comments/3/reactions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusCreated) w.Write([]byte(`{"id":1,"user":{"login":"l","id":2},"content":"+1"}`)) }) got, _, err := client.Reactions.CreateTeamDiscussionCommentReaction(context.Background(), 1, 2, 3, "+1") if err != nil { t.Errorf("CreateTeamDiscussionCommentReaction returned error: %v", err) } want := &Reaction{ID: Int64(1), User: &User{Login: String("l"), ID: Int64(2)}, Content: String("+1")} if !reflect.DeepEqual(got, want) { t.Errorf("CreateTeamDiscussionCommentReaction = %+v, want %+v", got, want) } } func TestReactionsService_DeleteReaction(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/reactions/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeReactionsPreview) w.WriteHeader(http.StatusNoContent) }) if _, err := client.Reactions.DeleteReaction(context.Background(), 1); err != nil { t.Errorf("DeleteReaction returned error: %v", err) } } go-github-28.1.1/github/repos.go000066400000000000000000001410311353501270500164320ustar00rootroot00000000000000// 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" "strings" ) // RepositoriesService handles communication with the repository related // methods of the GitHub API. // // GitHub API docs: https://developer.github.com/v3/repos/ type RepositoriesService service // Repository represents a GitHub repository. type Repository struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` Owner *User `json:"owner,omitempty"` Name *string `json:"name,omitempty"` FullName *string `json:"full_name,omitempty"` Description *string `json:"description,omitempty"` Homepage *string `json:"homepage,omitempty"` CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"` DefaultBranch *string `json:"default_branch,omitempty"` MasterBranch *string `json:"master_branch,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` PushedAt *Timestamp `json:"pushed_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` HTMLURL *string `json:"html_url,omitempty"` CloneURL *string `json:"clone_url,omitempty"` GitURL *string `json:"git_url,omitempty"` MirrorURL *string `json:"mirror_url,omitempty"` SSHURL *string `json:"ssh_url,omitempty"` SVNURL *string `json:"svn_url,omitempty"` Language *string `json:"language,omitempty"` Fork *bool `json:"fork,omitempty"` ForksCount *int `json:"forks_count,omitempty"` NetworkCount *int `json:"network_count,omitempty"` OpenIssuesCount *int `json:"open_issues_count,omitempty"` StargazersCount *int `json:"stargazers_count,omitempty"` SubscribersCount *int `json:"subscribers_count,omitempty"` WatchersCount *int `json:"watchers_count,omitempty"` Size *int `json:"size,omitempty"` AutoInit *bool `json:"auto_init,omitempty"` Parent *Repository `json:"parent,omitempty"` Source *Repository `json:"source,omitempty"` TemplateRepository *Repository `json:"template_repository,omitempty"` Organization *Organization `json:"organization,omitempty"` Permissions *map[string]bool `json:"permissions,omitempty"` AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` Topics []string `json:"topics,omitempty"` Archived *bool `json:"archived,omitempty"` Disabled *bool `json:"disabled,omitempty"` // Only provided when using RepositoriesService.Get while in preview License *License `json:"license,omitempty"` // Additional mutable fields when creating and editing a repository Private *bool `json:"private,omitempty"` HasIssues *bool `json:"has_issues,omitempty"` HasWiki *bool `json:"has_wiki,omitempty"` HasPages *bool `json:"has_pages,omitempty"` HasProjects *bool `json:"has_projects,omitempty"` HasDownloads *bool `json:"has_downloads,omitempty"` IsTemplate *bool `json:"is_template,omitempty"` LicenseTemplate *string `json:"license_template,omitempty"` GitignoreTemplate *string `json:"gitignore_template,omitempty"` // Creating an organization repository. Required for non-owners. TeamID *int64 `json:"team_id,omitempty"` // API URLs URL *string `json:"url,omitempty"` ArchiveURL *string `json:"archive_url,omitempty"` AssigneesURL *string `json:"assignees_url,omitempty"` BlobsURL *string `json:"blobs_url,omitempty"` BranchesURL *string `json:"branches_url,omitempty"` CollaboratorsURL *string `json:"collaborators_url,omitempty"` CommentsURL *string `json:"comments_url,omitempty"` CommitsURL *string `json:"commits_url,omitempty"` CompareURL *string `json:"compare_url,omitempty"` ContentsURL *string `json:"contents_url,omitempty"` ContributorsURL *string `json:"contributors_url,omitempty"` DeploymentsURL *string `json:"deployments_url,omitempty"` DownloadsURL *string `json:"downloads_url,omitempty"` EventsURL *string `json:"events_url,omitempty"` ForksURL *string `json:"forks_url,omitempty"` GitCommitsURL *string `json:"git_commits_url,omitempty"` GitRefsURL *string `json:"git_refs_url,omitempty"` GitTagsURL *string `json:"git_tags_url,omitempty"` HooksURL *string `json:"hooks_url,omitempty"` IssueCommentURL *string `json:"issue_comment_url,omitempty"` IssueEventsURL *string `json:"issue_events_url,omitempty"` IssuesURL *string `json:"issues_url,omitempty"` KeysURL *string `json:"keys_url,omitempty"` LabelsURL *string `json:"labels_url,omitempty"` LanguagesURL *string `json:"languages_url,omitempty"` MergesURL *string `json:"merges_url,omitempty"` MilestonesURL *string `json:"milestones_url,omitempty"` NotificationsURL *string `json:"notifications_url,omitempty"` PullsURL *string `json:"pulls_url,omitempty"` ReleasesURL *string `json:"releases_url,omitempty"` StargazersURL *string `json:"stargazers_url,omitempty"` StatusesURL *string `json:"statuses_url,omitempty"` SubscribersURL *string `json:"subscribers_url,omitempty"` SubscriptionURL *string `json:"subscription_url,omitempty"` TagsURL *string `json:"tags_url,omitempty"` TreesURL *string `json:"trees_url,omitempty"` TeamsURL *string `json:"teams_url,omitempty"` // TextMatches is only populated from search results that request text matches // See: search.go and https://developer.github.com/v3/search/#text-match-metadata TextMatches []TextMatch `json:"text_matches,omitempty"` } func (r Repository) String() string { return Stringify(r) } // RepositoryListOptions specifies the optional parameters to the // RepositoriesService.List method. type RepositoryListOptions struct { // Visibility of repositories to list. Can be one of all, public, or private. // Default: all Visibility string `url:"visibility,omitempty"` // List repos of given affiliation[s]. // Comma-separated list of values. Can include: // * owner: Repositories that are owned by the authenticated user. // * collaborator: Repositories that the user has been added to as a // collaborator. // * organization_member: Repositories that the user has access to through // being a member of an organization. This includes every repository on // every team that the user is on. // Default: owner,collaborator,organization_member Affiliation string `url:"affiliation,omitempty"` // Type of repositories to list. // Can be one of all, owner, public, private, member. Default: all // Will cause a 422 error if used in the same request as visibility or // affiliation. Type string `url:"type,omitempty"` // How to sort the repository list. Can be one of created, updated, pushed, // full_name. Default: full_name Sort string `url:"sort,omitempty"` // Direction in which to sort repositories. Can be one of asc or desc. // Default: when using full_name: asc; otherwise desc Direction string `url:"direction,omitempty"` ListOptions } // 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 func (s *RepositoriesService) List(ctx context.Context, user string, opt *RepositoryListOptions) ([]*Repository, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/repos", user) } else { u = "user/repos" } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. acceptHeaders := []string{mediaTypeTopicsPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var repos []*Repository resp, err := s.client.Do(ctx, req, &repos) if err != nil { return nil, resp, err } return repos, resp, nil } // RepositoryListByOrgOptions specifies the optional parameters to the // RepositoriesService.ListByOrg method. type RepositoryListByOrgOptions struct { // Type of repositories to list. Possible values are: all, public, private, // forks, sources, member. Default is "all". Type string `url:"type,omitempty"` ListOptions } // ListByOrg lists the repositories for an organization. // // GitHub API docs: https://developer.github.com/v3/repos/#list-organization-repositories func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opt *RepositoryListByOrgOptions) ([]*Repository, *Response, error) { u := fmt.Sprintf("orgs/%v/repos", org) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. acceptHeaders := []string{mediaTypeTopicsPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var repos []*Repository resp, err := s.client.Do(ctx, req, &repos) if err != nil { return nil, resp, err } return repos, resp, nil } // RepositoryListAllOptions specifies the optional parameters to the // RepositoriesService.ListAll method. type RepositoryListAllOptions struct { // ID of the last repository seen Since int64 `url:"since,omitempty"` } // 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 func (s *RepositoriesService) ListAll(ctx context.Context, opt *RepositoryListAllOptions) ([]*Repository, *Response, error) { u, err := addOptions("repositories", opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var repos []*Repository resp, err := s.client.Do(ctx, req, &repos) if err != nil { return nil, resp, err } return repos, resp, nil } // createRepoRequest is a subset of Repository and is used internally // by Create to pass only the known fields for the endpoint. // // See https://github.com/google/go-github/issues/1014 for more // information. type createRepoRequest struct { // Name is required when creating a repo. Name *string `json:"name,omitempty"` Description *string `json:"description,omitempty"` Homepage *string `json:"homepage,omitempty"` Private *bool `json:"private,omitempty"` HasIssues *bool `json:"has_issues,omitempty"` HasProjects *bool `json:"has_projects,omitempty"` HasWiki *bool `json:"has_wiki,omitempty"` IsTemplate *bool `json:"is_template,omitempty"` // Creating an organization repository. Required for non-owners. TeamID *int64 `json:"team_id,omitempty"` AutoInit *bool `json:"auto_init,omitempty"` GitignoreTemplate *string `json:"gitignore_template,omitempty"` LicenseTemplate *string `json:"license_template,omitempty"` AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` } // Create a new repository. If an organization is specified, the new // repository will be created under that org. If the empty string is // specified, it will be created for the authenticated user. // // 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 func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { var u string if org != "" { u = fmt.Sprintf("orgs/%v/repos", org) } else { u = "user/repos" } repoReq := &createRepoRequest{ Name: repo.Name, Description: repo.Description, Homepage: repo.Homepage, Private: repo.Private, HasIssues: repo.HasIssues, HasProjects: repo.HasProjects, HasWiki: repo.HasWiki, IsTemplate: repo.IsTemplate, TeamID: repo.TeamID, AutoInit: repo.AutoInit, GitignoreTemplate: repo.GitignoreTemplate, LicenseTemplate: repo.LicenseTemplate, AllowSquashMerge: repo.AllowSquashMerge, AllowMergeCommit: repo.AllowMergeCommit, AllowRebaseMerge: repo.AllowRebaseMerge, } req, err := s.client.NewRequest("POST", u, repoReq) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeRepositoryTemplatePreview) r := new(Repository) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // TemplateRepoRequest represents a request to create a repository from a template. type TemplateRepoRequest struct { // Name is required when creating a repo. Name *string `json:"name,omitempty"` Owner *string `json:"owner,omitempty"` Description *string `json:"description,omitempty"` Private *bool `json:"private,omitempty"` } // CreateFromTemplate generates a repository from a template. // // GitHub API docs: https://developer.github.com/v3/repos/#create-repository-using-a-repository-template func (s *RepositoriesService) CreateFromTemplate(ctx context.Context, templateOwner, templateRepo string, templateRepoReq *TemplateRepoRequest) (*Repository, *Response, error) { u := fmt.Sprintf("repos/%v/%v/generate", templateOwner, templateRepo) req, err := s.client.NewRequest("POST", u, templateRepoReq) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeRepositoryTemplatePreview) r := new(Repository) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // Get fetches a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#get 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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when the license support fully launches // https://developer.github.com/v3/licenses/#get-a-repositorys-license acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview, mediaTypeRepositoryTemplatePreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) repository := new(Repository) resp, err := s.client.Do(ctx, req, repository) if err != nil { return nil, resp, err } return repository, resp, nil } // GetCodeOfConduct gets the contents of a repository's code of conduct. // // GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#get-the-contents-of-a-repositorys-code-of-conduct func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) { u := fmt.Sprintf("repos/%v/%v/community/code_of_conduct", owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeCodesOfConductPreview) coc := new(CodeOfConduct) resp, err := s.client.Do(ctx, req, coc) if err != nil { return nil, resp, err } return coc, resp, nil } // GetByID fetches a repository. // // Note: GetByID uses the undocumented GitHub API endpoint /repositories/:id. func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repository, *Response, error) { u := fmt.Sprintf("repositories/%d", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } repository := new(Repository) resp, err := s.client.Do(ctx, req, repository) if err != nil { return nil, resp, err } return repository, resp, nil } // Edit updates a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#edit 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) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeRepositoryTemplatePreview) r := new(Repository) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // Delete a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#delete-a-repository func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v", owner, repo) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // Contributor represents a repository contributor type Contributor struct { Login *string `json:"login,omitempty"` ID *int64 `json:"id,omitempty"` AvatarURL *string `json:"avatar_url,omitempty"` GravatarID *string `json:"gravatar_id,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` FollowersURL *string `json:"followers_url,omitempty"` FollowingURL *string `json:"following_url,omitempty"` GistsURL *string `json:"gists_url,omitempty"` StarredURL *string `json:"starred_url,omitempty"` SubscriptionsURL *string `json:"subscriptions_url,omitempty"` OrganizationsURL *string `json:"organizations_url,omitempty"` ReposURL *string `json:"repos_url,omitempty"` EventsURL *string `json:"events_url,omitempty"` ReceivedEventsURL *string `json:"received_events_url,omitempty"` Type *string `json:"type,omitempty"` SiteAdmin *bool `json:"site_admin,omitempty"` Contributions *int `json:"contributions,omitempty"` } // ListContributorsOptions specifies the optional parameters to the // RepositoriesService.ListContributors method. type ListContributorsOptions struct { // Include anonymous contributors in results or not Anon string `url:"anon,omitempty"` ListOptions } // EnableVulnerabilityAlerts enables vulnerability alerts and the dependency graph for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#enable-vulnerability-alerts func (s *RepositoriesService) EnableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) return s.client.Do(ctx, req, nil) } // DisableVulnerabilityAlerts disables vulnerability alerts and the dependency graph for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#disable-vulnerability-alerts func (s *RepositoriesService) DisableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) return s.client.Do(ctx, req, nil) } // EnableAutomatedSecurityFixes enables the automated security fixes for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#enable-automated-security-fixes func (s *RepositoriesService) EnableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview) return s.client.Do(ctx, req, nil) } // DisableAutomatedSecurityFixes disables vulnerability alerts and the dependency graph for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#disable-automated-security-fixes func (s *RepositoriesService) DisableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview) return s.client.Do(ctx, req, nil) } // ListContributors lists contributors for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#list-contributors func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opt *ListContributorsOptions) ([]*Contributor, *Response, error) { u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var contributor []*Contributor resp, err := s.client.Do(ctx, req, &contributor) if err != nil { return nil, nil, err } return contributor, resp, nil } // ListLanguages lists languages for the specified repository. The returned map // specifies the languages and the number of bytes of code written in that // language. For example: // // { // "C": 78769, // "Python": 7769 // } // // GitHub API docs: https://developer.github.com/v3/repos/#list-languages func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) { u := fmt.Sprintf("repos/%v/%v/languages", owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } languages := make(map[string]int) resp, err := s.client.Do(ctx, req, &languages) if err != nil { return nil, resp, err } return languages, resp, nil } // ListTeams lists the teams for the specified repository. // // GitHub API docs: https://developer.github.com/v3/repos/#list-teams func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Team, *Response, error) { u := fmt.Sprintf("repos/%v/%v/teams", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeNestedTeamsPreview) var teams []*Team resp, err := s.client.Do(ctx, req, &teams) if err != nil { return nil, resp, err } return teams, resp, nil } // RepositoryTag represents a repository tag. type RepositoryTag struct { Name *string `json:"name,omitempty"` Commit *Commit `json:"commit,omitempty"` ZipballURL *string `json:"zipball_url,omitempty"` TarballURL *string `json:"tarball_url,omitempty"` } // ListTags lists tags for the specified repository. // // GitHub API docs: https://developer.github.com/v3/repos/#list-tags func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*RepositoryTag, *Response, error) { u := fmt.Sprintf("repos/%v/%v/tags", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var tags []*RepositoryTag resp, err := s.client.Do(ctx, req, &tags) if err != nil { return nil, resp, err } return tags, resp, nil } // Branch represents a repository branch type Branch struct { Name *string `json:"name,omitempty"` Commit *RepositoryCommit `json:"commit,omitempty"` Protected *bool `json:"protected,omitempty"` } // Protection represents a repository branch's protection. type Protection struct { RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` EnforceAdmins *AdminEnforcement `json:"enforce_admins"` Restrictions *BranchRestrictions `json:"restrictions"` } // ProtectionRequest represents a request to create/edit a branch's protection. type ProtectionRequest struct { RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"` EnforceAdmins bool `json:"enforce_admins"` Restrictions *BranchRestrictionsRequest `json:"restrictions"` } // RequiredStatusChecks represents the protection status of a individual branch. type RequiredStatusChecks struct { // Require branches to be up to date before merging. (Required.) Strict bool `json:"strict"` // The list of status checks to require in order to merge into this // branch. (Required; use []string{} instead of nil for empty list.) Contexts []string `json:"contexts"` } // RequiredStatusChecksRequest represents a request to edit a protected branch's status checks. type RequiredStatusChecksRequest struct { Strict *bool `json:"strict,omitempty"` Contexts []string `json:"contexts,omitempty"` } // PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch. type PullRequestReviewsEnforcement struct { // Specifies which users and teams can dismiss pull request reviews. DismissalRestrictions DismissalRestrictions `json:"dismissal_restrictions"` // Specifies if approved reviews are dismissed automatically, when a new commit is pushed. DismissStaleReviews bool `json:"dismiss_stale_reviews"` // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. // Valid values are 1-6. RequiredApprovingReviewCount int `json:"required_approving_review_count"` } // PullRequestReviewsEnforcementRequest represents request to set the pull request review // enforcement of a protected branch. It is separate from PullRequestReviewsEnforcement above // because the request structure is different from the response structure. type PullRequestReviewsEnforcementRequest struct { // Specifies which users and teams should be allowed to dismiss pull request reviews. // User and team dismissal restrictions are only available for // organization-owned repositories. Must be nil for personal repositories. DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. (Required) DismissStaleReviews bool `json:"dismiss_stale_reviews"` // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. // Valid values are 1-6. RequiredApprovingReviewCount int `json:"required_approving_review_count"` } // PullRequestReviewsEnforcementUpdate represents request to patch the pull request review // enforcement of a protected branch. It is separate from PullRequestReviewsEnforcementRequest above // because the patch request does not require all fields to be initialized. type PullRequestReviewsEnforcementUpdate struct { // Specifies which users and teams can dismiss pull request reviews. Can be omitted. DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. Can be omitted. DismissStaleReviews *bool `json:"dismiss_stale_reviews,omitempty"` // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. RequireCodeOwnerReviews bool `json:"require_code_owner_reviews,omitempty"` // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. // Valid values are 1 - 6. RequiredApprovingReviewCount int `json:"required_approving_review_count"` } // AdminEnforcement represents the configuration to enforce required status checks for repository administrators. type AdminEnforcement struct { URL *string `json:"url,omitempty"` Enabled bool `json:"enabled"` } // BranchRestrictions represents the restriction that only certain users or // teams may push to a branch. type BranchRestrictions struct { // The list of user logins with push access. Users []*User `json:"users"` // The list of team slugs with push access. Teams []*Team `json:"teams"` } // BranchRestrictionsRequest represents the request to create/edit the // restriction that only certain users or teams may push to a branch. It is // separate from BranchRestrictions above because the request structure is // different from the response structure. type BranchRestrictionsRequest struct { // The list of user logins with push access. (Required; use []string{} instead of nil for empty list.) Users []string `json:"users"` // The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.) Teams []string `json:"teams"` } // DismissalRestrictions specifies which users and teams can dismiss pull request reviews. type DismissalRestrictions struct { // The list of users who can dimiss pull request reviews. Users []*User `json:"users"` // The list of teams which can dismiss pull request reviews. Teams []*Team `json:"teams"` } // DismissalRestrictionsRequest represents the request to create/edit the // restriction to allows only specific users or teams to dimiss pull request reviews. It is // separate from DismissalRestrictions above because the request structure is // different from the response structure. // Note: Both Users and Teams must be nil, or both must be non-nil. type DismissalRestrictionsRequest struct { // The list of user logins who can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) Users *[]string `json:"users,omitempty"` // The list of team slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) Teams *[]string `json:"teams,omitempty"` } // SignaturesProtectedBranch represents the protection status of an individual branch. type SignaturesProtectedBranch struct { URL *string `json:"url,omitempty"` // Commits pushed to matching branches must have verified signatures. Enabled *bool `json:"enabled,omitempty"` } // ListBranches lists branches for the specified repository. // // GitHub API docs: https://developer.github.com/v3/repos/#list-branches func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Branch, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) var branches []*Branch resp, err := s.client.Do(ctx, req, &branches) if err != nil { return nil, resp, err } return branches, resp, nil } // GetBranch gets the specified branch for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) b := new(Branch) resp, err := s.client.Do(ctx, req, b) if err != nil { return nil, resp, err } return b, resp, nil } // GetBranchProtection gets the protection of a given branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-branch-protection func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) p := new(Protection) resp, err := s.client.Do(ctx, req, p) if err != nil { return nil, resp, err } return p, resp, nil } // GetRequiredStatusChecks gets the required status checks for a given protected branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-required-status-checks-of-protected-branch func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) p := new(RequiredStatusChecks) resp, err := s.client.Do(ctx, req, p) if err != nil { return nil, resp, err } return p, resp, nil } // ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#list-required-status-checks-contexts-of-protected-branch func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) resp, err = s.client.Do(ctx, req, &contexts) if err != nil { return nil, resp, err } return contexts, resp, nil } // UpdateBranchProtection updates the protection of a given branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#update-branch-protection func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) req, err := s.client.NewRequest("PUT", u, preq) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) p := new(Protection) resp, err := s.client.Do(ctx, req, p) if err != nil { return nil, resp, err } return p, resp, nil } // RemoveBranchProtection removes the protection of a given branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-branch-protection func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) return s.client.Do(ctx, req, nil) } // GetSignaturesProtectedBranch gets required signatures of protected branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-required-signatures-of-protected-branch func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeSignaturePreview) p := new(SignaturesProtectedBranch) resp, err := s.client.Do(ctx, req, p) if err != nil { return nil, resp, err } return p, resp, nil } // RequireSignaturesOnProtectedBranch makes signed commits required on a protected branch. // It requires admin access and branch protection to be enabled. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#add-required-signatures-of-protected-branch func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeSignaturePreview) r := new(SignaturesProtectedBranch) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, err } // OptionalSignaturesOnProtectedBranch removes required signed commits on a given branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-required-signatures-of-protected-branch func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeSignaturePreview) return s.client.Do(ctx, req, nil) } // UpdateRequiredStatusChecks updates the required status checks for a given protected branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) req, err := s.client.NewRequest("PATCH", u, sreq) if err != nil { return nil, nil, err } sc := new(RequiredStatusChecks) resp, err := s.client.Do(ctx, req, sc) if err != nil { return nil, resp, err } return sc, resp, nil } // License gets the contents of a repository's license if one is detected. // // GitHub API docs: https://developer.github.com/v3/licenses/#get-the-contents-of-a-repositorys-license func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) { u := fmt.Sprintf("repos/%v/%v/license", owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } r := &RepositoryLicense{} resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-pull-request-review-enforcement-of-protected-branch func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) r := new(PullRequestReviewsEnforcement) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch. // It requires admin access and branch protection to be enabled. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) req, err := s.client.NewRequest("PATCH", u, patch) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) r := new(PullRequestReviewsEnforcement) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, err } // DisableDismissalRestrictions disables dismissal restrictions of a protected branch. // It requires admin access and branch protection to be enabled. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) data := struct { R []interface{} `json:"dismissal_restrictions"` }{[]interface{}{}} req, err := s.client.NewRequest("PATCH", u, data) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) r := new(PullRequestReviewsEnforcement) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, err } // RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-pull-request-review-enforcement-of-protected-branch func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) return s.client.Do(ctx, req, nil) } // GetAdminEnforcement gets admin enforcement information of a protected branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#get-admin-enforcement-of-protected-branch func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) r := new(AdminEnforcement) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // AddAdminEnforcement adds admin enforcement to a protected branch. // It requires admin access and branch protection to be enabled. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#add-admin-enforcement-of-protected-branch func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) r := new(AdminEnforcement) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, err } // RemoveAdminEnforcement removes admin enforcement from a protected branch. // // GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-admin-enforcement-of-protected-branch func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) return s.client.Do(ctx, req, nil) } // repositoryTopics represents a collection of repository topics. type repositoryTopics struct { Names []string `json:"names"` } // ListAllTopics lists topics for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#list-all-topics-for-a-repository 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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTopicsPreview) topics := new(repositoryTopics) resp, err := s.client.Do(ctx, req, topics) if err != nil { return nil, resp, err } return topics.Names, resp, nil } // ReplaceAllTopics replaces topics for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/#replace-all-topics-for-a-repository 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{ Names: topics, } if t.Names == nil { t.Names = []string{} } req, err := s.client.NewRequest("PUT", u, t) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTopicsPreview) t = new(repositoryTopics) resp, err := s.client.Do(ctx, req, t) if err != nil { return nil, resp, err } return t.Names, resp, nil } // TransferRequest represents a request to transfer a repository. type TransferRequest struct { NewOwner string `json:"new_owner"` TeamID []int64 `json:"team_ids,omitempty"` } // Transfer transfers a repository from one account or organization to another. // // This method might return an *AcceptedError and a status code of // 202. This is because this is the status that GitHub returns to signify that // it has now scheduled the transfer of the repository in a background task. // A follow up request, after a delay of a second or so, should result // in a successful request. // // GitHub API docs: https://developer.github.com/v3/repos/#transfer-a-repository func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string, transfer TransferRequest) (*Repository, *Response, error) { u := fmt.Sprintf("repos/%v/%v/transfer", owner, repo) req, err := s.client.NewRequest("POST", u, &transfer) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeRepositoryTransferPreview) r := new(Repository) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } go-github-28.1.1/github/repos_collaborators.go000066400000000000000000000117451353501270500213700ustar00rootroot00000000000000// 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" ) // ListCollaboratorsOptions specifies the optional parameters to the // RepositoriesService.ListCollaborators method. type ListCollaboratorsOptions struct { // Affiliation specifies how collaborators should be filtered by their affiliation. // Possible values are: // outside - All outside collaborators of an organization-owned repository // direct - All collaborators with permissions to an organization-owned repository, // regardless of organization membership status // all - All collaborators the authenticated user can see // // Default value is "all". Affiliation string `url:"affiliation,omitempty"` ListOptions } // ListCollaborators lists the GitHub users that have access to the repository. // // GitHub API docs: https://developer.github.com/v3/repos/collaborators/#list-collaborators func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo string, opt *ListCollaboratorsOptions) ([]*User, *Response, error) { u := fmt.Sprintf("repos/%v/%v/collaborators", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeNestedTeamsPreview) var users []*User resp, err := s.client.Do(ctx, req, &users) if err != nil { return nil, resp, err } return users, resp, nil } // IsCollaborator checks whether the specified GitHub user has collaborator // access to the given 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 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) if err != nil { return false, nil, err } resp, err := s.client.Do(ctx, req, nil) isCollab, err := parseBoolResponse(err) return isCollab, resp, err } // RepositoryPermissionLevel represents the permission level an organization // member has for a given repository. type RepositoryPermissionLevel struct { // Possible values: "admin", "write", "read", "none" Permission *string `json:"permission,omitempty"` User *User `json:"user,omitempty"` } // GetPermissionLevel retrieves the specific permission level a collaborator has for a given repository. // GitHub API docs: https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level func (s *RepositoriesService) GetPermissionLevel(ctx context.Context, owner, repo, user string) (*RepositoryPermissionLevel, *Response, error) { u := fmt.Sprintf("repos/%v/%v/collaborators/%v/permission", owner, repo, user) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } rpl := new(RepositoryPermissionLevel) resp, err := s.client.Do(ctx, req, rpl) if err != nil { return nil, resp, err } return rpl, resp, nil } // RepositoryAddCollaboratorOptions specifies the optional parameters to the // RepositoriesService.AddCollaborator method. type RepositoryAddCollaboratorOptions struct { // Permission specifies the permission to grant the user on this repository. // Possible values are: // pull - team members can pull, but not push to or administer this repository // push - team members can pull and push, but not administer this repository // admin - team members can pull, push and administer this repository // // Default value is "push". This option is only valid for organization-owned repositories. Permission string `json:"permission,omitempty"` } // AddCollaborator sends an invitation to the specified GitHub user // to become a collaborator to the given repo. // // GitHub API docs: https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator func (s *RepositoriesService) AddCollaborator(ctx context.Context, owner, repo, user string, opt *RepositoryAddCollaboratorOptions) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // 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 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) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/repos_collaborators_test.go000066400000000000000000000133761353501270500224310ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestRepositoriesService_ListCollaborators(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/collaborators", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprintf(w, `[{"id":1}, {"id":2}]`) }) opt := &ListCollaboratorsOptions{ ListOptions: ListOptions{Page: 2}, } users, _, err := client.Repositories.ListCollaborators(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListCollaborators returned error: %v", err) } want := []*User{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(users, want) { t.Errorf("Repositories.ListCollaborators returned %+v, want %+v", users, want) } } func TestRepositoriesService_ListCollaborators_withAffiliation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/collaborators", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"affiliation": "all", "page": "2"}) fmt.Fprintf(w, `[{"id":1}, {"id":2}]`) }) opt := &ListCollaboratorsOptions{ ListOptions: ListOptions{Page: 2}, Affiliation: "all", } users, _, err := client.Repositories.ListCollaborators(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListCollaborators returned error: %v", err) } want := []*User{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(users, want) { t.Errorf("Repositories.ListCollaborators returned %+v, want %+v", users, want) } } func TestRepositoriesService_ListCollaborators_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.ListCollaborators(context.Background(), "%", "%", nil) testURLParseError(t, err) } func TestRepositoriesService_IsCollaborator_True(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/collaborators/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNoContent) }) isCollab, _, err := client.Repositories.IsCollaborator(context.Background(), "o", "r", "u") if err != nil { t.Errorf("Repositories.IsCollaborator returned error: %v", err) } if !isCollab { t.Errorf("Repositories.IsCollaborator returned false, want true") } } func TestRepositoriesService_IsCollaborator_False(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/collaborators/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) isCollab, _, err := client.Repositories.IsCollaborator(context.Background(), "o", "r", "u") if err != nil { t.Errorf("Repositories.IsCollaborator returned error: %v", err) } if isCollab { t.Errorf("Repositories.IsCollaborator returned true, want false") } } func TestRepositoriesService_IsCollaborator_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.IsCollaborator(context.Background(), "%", "%", "%") testURLParseError(t, err) } func TestRepositoryService_GetPermissionLevel(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/collaborators/u/permission", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprintf(w, `{"permission":"admin","user":{"login":"u"}}`) }) rpl, _, err := client.Repositories.GetPermissionLevel(context.Background(), "o", "r", "u") if err != nil { t.Errorf("Repositories.GetPermissionLevel returned error: %v", err) } want := &RepositoryPermissionLevel{ Permission: String("admin"), User: &User{ Login: String("u"), }, } if !reflect.DeepEqual(rpl, want) { t.Errorf("Repositories.GetPermissionLevel returned %+v, want %+v", rpl, want) } } func TestRepositoriesService_AddCollaborator(t *testing.T) { client, mux, _, teardown := setup() defer teardown() opt := &RepositoryAddCollaboratorOptions{Permission: "admin"} mux.HandleFunc("/repos/o/r/collaborators/u", func(w http.ResponseWriter, r *http.Request) { v := new(RepositoryAddCollaboratorOptions) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, opt) { t.Errorf("Request body = %+v, want %+v", v, opt) } w.WriteHeader(http.StatusNoContent) }) _, err := client.Repositories.AddCollaborator(context.Background(), "o", "r", "u", opt) if err != nil { t.Errorf("Repositories.AddCollaborator returned error: %v", err) } } func TestRepositoriesService_AddCollaborator_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Repositories.AddCollaborator(context.Background(), "%", "%", "%", nil) testURLParseError(t, err) } func TestRepositoriesService_RemoveCollaborator(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/collaborators/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Repositories.RemoveCollaborator(context.Background(), "o", "r", "u") if err != nil { t.Errorf("Repositories.RemoveCollaborator returned error: %v", err) } } func TestRepositoriesService_RemoveCollaborator_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Repositories.RemoveCollaborator(context.Background(), "%", "%", "%") testURLParseError(t, err) } go-github-28.1.1/github/repos_comments.go000066400000000000000000000120501353501270500203350ustar00rootroot00000000000000// 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" "time" ) // RepositoryComment represents a comment for a commit, file, or line in a repository. type RepositoryComment struct { HTMLURL *string `json:"html_url,omitempty"` URL *string `json:"url,omitempty"` ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` CommitID *string `json:"commit_id,omitempty"` User *User `json:"user,omitempty"` Reactions *Reactions `json:"reactions,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` // User-mutable fields Body *string `json:"body"` // User-initialized fields Path *string `json:"path,omitempty"` Position *int `json:"position,omitempty"` } func (r RepositoryComment) String() string { return Stringify(r) } // ListComments lists all the comments for the repository. // // GitHub API docs: https://developer.github.com/v3/repos/comments/#list-commit-comments-for-a-repository func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/comments", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeReactionsPreview) var comments []*RepositoryComment resp, err := s.client.Do(ctx, req, &comments) if err != nil { return nil, resp, err } return comments, resp, nil } // ListCommitComments lists all the comments for a given commit SHA. // // GitHub API docs: https://developer.github.com/v3/repos/comments/#list-comments-for-a-single-commit func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, repo, sha string, opt *ListOptions) ([]*RepositoryComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeReactionsPreview) var comments []*RepositoryComment resp, err := s.client.Do(ctx, req, &comments) if err != nil { return nil, resp, err } return comments, resp, nil } // CreateComment creates a comment for the given commit. // Note: GitHub allows for comments to be created for non-existing files and positions. // // GitHub API docs: https://developer.github.com/v3/repos/comments/#create-a-commit-comment func (s *RepositoriesService) CreateComment(ctx context.Context, owner, repo, sha string, comment *RepositoryComment) (*RepositoryComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) req, err := s.client.NewRequest("POST", u, comment) if err != nil { return nil, nil, err } c := new(RepositoryComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // GetComment gets a single comment from a repository. // // GitHub API docs: https://developer.github.com/v3/repos/comments/#get-a-single-commit-comment func (s *RepositoriesService) GetComment(ctx context.Context, owner, repo string, id int64) (*RepositoryComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeReactionsPreview) c := new(RepositoryComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // UpdateComment updates the body of a single comment. // // GitHub API docs: https://developer.github.com/v3/repos/comments/#update-a-commit-comment func (s *RepositoriesService) UpdateComment(ctx context.Context, owner, repo string, id int64, comment *RepositoryComment) (*RepositoryComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) req, err := s.client.NewRequest("PATCH", u, comment) if err != nil { return nil, nil, err } c := new(RepositoryComment) resp, err := s.client.Do(ctx, req, c) if err != nil { return nil, resp, err } return c, resp, nil } // DeleteComment deletes a single comment from a repository. // // GitHub API docs: https://developer.github.com/v3/repos/comments/#delete-a-commit-comment func (s *RepositoriesService) DeleteComment(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/repos_comments_test.go000066400000000000000000000135571353501270500214110ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestRepositoriesService_ListComments(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/comments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}, {"id":2}]`) }) opt := &ListOptions{Page: 2} comments, _, err := client.Repositories.ListComments(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListComments returned error: %v", err) } want := []*RepositoryComment{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(comments, want) { t.Errorf("Repositories.ListComments returned %+v, want %+v", comments, want) } } func TestRepositoriesService_ListComments_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.ListComments(context.Background(), "%", "%", nil) testURLParseError(t, err) } func TestRepositoriesService_ListCommitComments(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/commits/s/comments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}, {"id":2}]`) }) opt := &ListOptions{Page: 2} comments, _, err := client.Repositories.ListCommitComments(context.Background(), "o", "r", "s", opt) if err != nil { t.Errorf("Repositories.ListCommitComments returned error: %v", err) } want := []*RepositoryComment{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(comments, want) { t.Errorf("Repositories.ListCommitComments returned %+v, want %+v", comments, want) } } func TestRepositoriesService_ListCommitComments_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.ListCommitComments(context.Background(), "%", "%", "%", nil) testURLParseError(t, err) } func TestRepositoriesService_CreateComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &RepositoryComment{Body: String("b")} mux.HandleFunc("/repos/o/r/commits/s/comments", func(w http.ResponseWriter, r *http.Request) { v := new(RepositoryComment) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) comment, _, err := client.Repositories.CreateComment(context.Background(), "o", "r", "s", input) if err != nil { t.Errorf("Repositories.CreateComment returned error: %v", err) } want := &RepositoryComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("Repositories.CreateComment returned %+v, want %+v", comment, want) } } func TestRepositoriesService_CreateComment_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.CreateComment(context.Background(), "%", "%", "%", nil) testURLParseError(t, err) } func TestRepositoriesService_GetComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/comments/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeReactionsPreview) fmt.Fprint(w, `{"id":1}`) }) comment, _, err := client.Repositories.GetComment(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.GetComment returned error: %v", err) } want := &RepositoryComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("Repositories.GetComment returned %+v, want %+v", comment, want) } } func TestRepositoriesService_GetComment_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.GetComment(context.Background(), "%", "%", 1) testURLParseError(t, err) } func TestRepositoriesService_UpdateComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &RepositoryComment{Body: String("b")} mux.HandleFunc("/repos/o/r/comments/1", func(w http.ResponseWriter, r *http.Request) { v := new(RepositoryComment) 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}`) }) comment, _, err := client.Repositories.UpdateComment(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Repositories.UpdateComment returned error: %v", err) } want := &RepositoryComment{ID: Int64(1)} if !reflect.DeepEqual(comment, want) { t.Errorf("Repositories.UpdateComment returned %+v, want %+v", comment, want) } } func TestRepositoriesService_UpdateComment_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.UpdateComment(context.Background(), "%", "%", 1, nil) testURLParseError(t, err) } func TestRepositoriesService_DeleteComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/comments/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Repositories.DeleteComment(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.DeleteComment returned error: %v", err) } } func TestRepositoriesService_DeleteComment_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Repositories.DeleteComment(context.Background(), "%", "%", 1) testURLParseError(t, err) } go-github-28.1.1/github/repos_commits.go000066400000000000000000000206751353501270500201770ustar00rootroot00000000000000// 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 ( "bytes" "context" "fmt" "net/url" "time" ) // RepositoryCommit represents a commit in a repo. // Note that it's wrapping a Commit, so author/committer information is in two places, // but contain different details about them: in RepositoryCommit "github details", in Commit - "git details". type RepositoryCommit struct { NodeID *string `json:"node_id,omitempty"` SHA *string `json:"sha,omitempty"` Commit *Commit `json:"commit,omitempty"` Author *User `json:"author,omitempty"` Committer *User `json:"committer,omitempty"` Parents []Commit `json:"parents,omitempty"` HTMLURL *string `json:"html_url,omitempty"` URL *string `json:"url,omitempty"` CommentsURL *string `json:"comments_url,omitempty"` // Details about how many changes were made in this commit. Only filled in during GetCommit! Stats *CommitStats `json:"stats,omitempty"` // Details about which files, and how this commit touched. Only filled in during GetCommit! Files []CommitFile `json:"files,omitempty"` } func (r RepositoryCommit) String() string { return Stringify(r) } // CommitStats represents the number of additions / deletions from a file in a given RepositoryCommit or GistCommit. type CommitStats struct { Additions *int `json:"additions,omitempty"` Deletions *int `json:"deletions,omitempty"` Total *int `json:"total,omitempty"` } func (c CommitStats) String() string { return Stringify(c) } // CommitFile represents a file modified in a commit. type CommitFile struct { SHA *string `json:"sha,omitempty"` Filename *string `json:"filename,omitempty"` Additions *int `json:"additions,omitempty"` Deletions *int `json:"deletions,omitempty"` Changes *int `json:"changes,omitempty"` Status *string `json:"status,omitempty"` Patch *string `json:"patch,omitempty"` BlobURL *string `json:"blob_url,omitempty"` RawURL *string `json:"raw_url,omitempty"` ContentsURL *string `json:"contents_url,omitempty"` PreviousFilename *string `json:"previous_filename,omitempty"` } func (c CommitFile) String() string { return Stringify(c) } // CommitsComparison is the result of comparing two commits. // See CompareCommits() for details. type CommitsComparison struct { BaseCommit *RepositoryCommit `json:"base_commit,omitempty"` MergeBaseCommit *RepositoryCommit `json:"merge_base_commit,omitempty"` // Head can be 'behind' or 'ahead' Status *string `json:"status,omitempty"` AheadBy *int `json:"ahead_by,omitempty"` BehindBy *int `json:"behind_by,omitempty"` TotalCommits *int `json:"total_commits,omitempty"` Commits []RepositoryCommit `json:"commits,omitempty"` Files []CommitFile `json:"files,omitempty"` HTMLURL *string `json:"html_url,omitempty"` PermalinkURL *string `json:"permalink_url,omitempty"` DiffURL *string `json:"diff_url,omitempty"` PatchURL *string `json:"patch_url,omitempty"` URL *string `json:"url,omitempty"` // API URL. } func (c CommitsComparison) String() string { return Stringify(c) } // CommitsListOptions specifies the optional parameters to the // RepositoriesService.ListCommits method. type CommitsListOptions struct { // SHA or branch to start listing Commits from. SHA string `url:"sha,omitempty"` // Path that should be touched by the returned Commits. Path string `url:"path,omitempty"` // Author of by which to filter Commits. Author string `url:"author,omitempty"` // Since when should Commits be included in the response. Since time.Time `url:"since,omitempty"` // Until when should Commits be included in the response. Until time.Time `url:"until,omitempty"` ListOptions } // BranchCommit is the result of listing branches with commit SHA. type BranchCommit struct { Name *string `json:"name,omitempty"` Commit *Commit `json:"commit,omitempty"` Protected *string `json:"protected,omitempty"` } // ListCommits lists the commits of a repository. // // GitHub API docs: https://developer.github.com/v3/repos/commits/#list func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opt *CommitsListOptions) ([]*RepositoryCommit, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var commits []*RepositoryCommit resp, err := s.client.Do(ctx, req, &commits) if err != nil { return nil, resp, err } return commits, resp, nil } // GetCommit fetches the specified commit, including all details about it. // // GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-single-commit // See also: https://developer.github.com/v3/git/commits/#get-a-single-commit provides the same functionality func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string) (*RepositoryCommit, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } commit := new(RepositoryCommit) resp, err := s.client.Do(ctx, req, commit) if err != nil { return nil, resp, err } return commit, resp, nil } // GetCommitRaw fetches the specified commit in raw (diff or patch) format. func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opt RawOptions) (string, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return "", nil, err } switch opt.Type { case Diff: req.Header.Set("Accept", mediaTypeV3Diff) case Patch: req.Header.Set("Accept", mediaTypeV3Patch) default: return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type) } var buf bytes.Buffer resp, err := s.client.Do(ctx, req, &buf) if err != nil { return "", resp, err } return buf.String(), resp, nil } // 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 func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, ref, lastSHA string) (string, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, url.QueryEscape(ref)) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return "", nil, err } if lastSHA != "" { req.Header.Set("If-None-Match", `"`+lastSHA+`"`) } req.Header.Set("Accept", mediaTypeV3SHA) var buf bytes.Buffer resp, err := s.client.Do(ctx, req, &buf) if err != nil { return "", resp, err } return buf.String(), resp, nil } // CompareCommits compares a range of commits with each other. // todo: support media formats - https://github.com/google/go-github/issues/6 // // GitHub API docs: https://developer.github.com/v3/repos/commits/#compare-two-commits func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo string, base, head string) (*CommitsComparison, *Response, error) { u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, base, head) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } comp := new(CommitsComparison) resp, err := s.client.Do(ctx, req, comp) if err != nil { return nil, resp, err } return comp, resp, nil } // ListBranchesHeadCommit gets all branches where the given commit SHA is the HEAD, // or latest commit for the branch. // // GitHub API docs: https://developer.github.com/v3/repos/commits/#list-branches-for-head-commit func (s *RepositoriesService) ListBranchesHeadCommit(ctx context.Context, owner, repo, sha string) ([]*BranchCommit, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/branches-where-head", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeListPullsOrBranchesForCommitPreview) var branchCommits []*BranchCommit resp, err := s.client.Do(ctx, req, &branchCommits) if err != nil { return nil, resp, err } return branchCommits, resp, nil } go-github-28.1.1/github/repos_commits_test.go000066400000000000000000000245401353501270500212310ustar00rootroot00000000000000// 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" "net/http" "reflect" "strings" "testing" "time" ) func TestRepositoriesService_ListCommits(t *testing.T) { client, mux, _, teardown := setup() defer teardown() // given mux.HandleFunc("/repos/o/r/commits", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "sha": "s", "path": "p", "author": "a", "since": "2013-08-01T00:00:00Z", "until": "2013-09-03T00:00:00Z", }) fmt.Fprintf(w, `[{"sha": "s"}]`) }) opt := &CommitsListOptions{ SHA: "s", Path: "p", Author: "a", Since: time.Date(2013, time.August, 1, 0, 0, 0, 0, time.UTC), Until: time.Date(2013, time.September, 3, 0, 0, 0, 0, time.UTC), } commits, _, err := client.Repositories.ListCommits(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListCommits returned error: %v", err) } want := []*RepositoryCommit{{SHA: String("s")}} if !reflect.DeepEqual(commits, want) { t.Errorf("Repositories.ListCommits returned %+v, want %+v", commits, want) } } func TestRepositoriesService_GetCommit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/commits/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprintf(w, `{ "sha": "s", "commit": { "message": "m" }, "author": { "login": "l" }, "committer": { "login": "l" }, "parents": [ { "sha": "s" } ], "stats": { "additions": 104, "deletions": 4, "total": 108 }, "files": [ { "filename": "f", "additions": 10, "deletions": 2, "changes": 12, "status": "s", "patch": "p", "blob_url": "b", "raw_url": "r", "contents_url": "c" } ] }`) }) commit, _, err := client.Repositories.GetCommit(context.Background(), "o", "r", "s") if err != nil { t.Errorf("Repositories.GetCommit returned error: %v", err) } want := &RepositoryCommit{ SHA: String("s"), Commit: &Commit{ Message: String("m"), }, Author: &User{ Login: String("l"), }, Committer: &User{ Login: String("l"), }, Parents: []Commit{ { SHA: String("s"), }, }, Stats: &CommitStats{ Additions: Int(104), Deletions: Int(4), Total: Int(108), }, Files: []CommitFile{ { Filename: String("f"), Additions: Int(10), Deletions: Int(2), Changes: Int(12), Status: String("s"), Patch: String("p"), BlobURL: String("b"), RawURL: String("r"), ContentsURL: String("c"), }, }, } if !reflect.DeepEqual(commit, want) { t.Errorf("Repositories.GetCommit returned \n%+v, want \n%+v", commit, want) } } func TestRepositoriesService_GetCommitRaw_diff(t *testing.T) { client, mux, _, teardown := setup() defer teardown() const rawStr = "@@diff content" mux.HandleFunc("/repos/o/r/commits/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeV3Diff) fmt.Fprint(w, rawStr) }) got, _, err := client.Repositories.GetCommitRaw(context.Background(), "o", "r", "s", RawOptions{Type: Diff}) if err != nil { t.Fatalf("Repositories.GetCommitRaw returned error: %v", err) } want := rawStr if got != want { t.Errorf("Repositories.GetCommitRaw returned %s want %s", got, want) } } func TestRepositoriesService_GetCommitRaw_patch(t *testing.T) { client, mux, _, teardown := setup() defer teardown() const rawStr = "@@patch content" mux.HandleFunc("/repos/o/r/commits/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeV3Patch) fmt.Fprint(w, rawStr) }) got, _, err := client.Repositories.GetCommitRaw(context.Background(), "o", "r", "s", RawOptions{Type: Patch}) if err != nil { t.Fatalf("Repositories.GetCommitRaw returned error: %v", err) } want := rawStr if got != want { t.Errorf("Repositories.GetCommitRaw returned %s want %s", got, want) } } func TestRepositoriesService_GetCommitRaw_invalid(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.GetCommitRaw(context.Background(), "o", "r", "s", RawOptions{100}) if err == nil { t.Fatal("Repositories.GetCommitRaw should return error") } if !strings.Contains(err.Error(), "unsupported raw type") { t.Error("Repositories.GetCommitRaw should return unsupported raw type error") } } func TestRepositoriesService_GetCommitSHA1(t *testing.T) { client, mux, _, teardown := setup() defer teardown() const sha1 = "01234abcde" mux.HandleFunc("/repos/o/r/commits/master", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeV3SHA) fmt.Fprintf(w, sha1) }) got, _, err := client.Repositories.GetCommitSHA1(context.Background(), "o", "r", "master", "") if err != nil { t.Errorf("Repositories.GetCommitSHA1 returned error: %v", err) } want := sha1 if got != want { t.Errorf("Repositories.GetCommitSHA1 = %v, want %v", got, want) } mux.HandleFunc("/repos/o/r/commits/tag", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeV3SHA) testHeader(t, r, "If-None-Match", `"`+sha1+`"`) w.WriteHeader(http.StatusNotModified) }) got, _, err = client.Repositories.GetCommitSHA1(context.Background(), "o", "r", "tag", sha1) if err == nil { t.Errorf("Expected HTTP 304 response") } want = "" if got != want { t.Errorf("Repositories.GetCommitSHA1 = %v, want %v", got, want) } } func TestRepositoriesService_NonAlphabetCharacter_GetCommitSHA1(t *testing.T) { client, mux, _, teardown := setup() defer teardown() const sha1 = "01234abcde" mux.HandleFunc("/repos/o/r/commits/master%20hash", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeV3SHA) fmt.Fprintf(w, sha1) }) got, _, err := client.Repositories.GetCommitSHA1(context.Background(), "o", "r", "master%20hash", "") if err != nil { t.Errorf("Repositories.GetCommitSHA1 returned error: %v", err) } if want := sha1; got != want { t.Errorf("Repositories.GetCommitSHA1 = %v, want %v", got, want) } mux.HandleFunc("/repos/o/r/commits/tag", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeV3SHA) testHeader(t, r, "If-None-Match", `"`+sha1+`"`) w.WriteHeader(http.StatusNotModified) }) got, _, err = client.Repositories.GetCommitSHA1(context.Background(), "o", "r", "tag", sha1) if err == nil { t.Errorf("Expected HTTP 304 response") } if want := ""; got != want { t.Errorf("Repositories.GetCommitSHA1 = %v, want %v", got, want) } } func TestRepositoriesService_CompareCommits(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/compare/b...h", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprintf(w, `{ "base_commit": { "sha": "s", "commit": { "author": { "name": "n" }, "committer": { "name": "n" }, "message": "m", "tree": { "sha": "t" } }, "author": { "login": "l" }, "committer": { "login": "l" }, "parents": [ { "sha": "s" } ] }, "status": "s", "ahead_by": 1, "behind_by": 2, "total_commits": 1, "commits": [ { "sha": "s", "commit": { "author": { "name": "n" } }, "author": { "login": "l" }, "committer": { "login": "l" }, "parents": [ { "sha": "s" } ] } ], "files": [ { "filename": "f" } ], "html_url": "https://github.com/o/r/compare/b...h", "permalink_url": "https://github.com/o/r/compare/o:bbcd538c8e72b8c175046e27cc8f907076331401...o:0328041d1152db8ae77652d1618a02e57f745f17", "diff_url": "https://github.com/o/r/compare/b...h.diff", "patch_url": "https://github.com/o/r/compare/b...h.patch", "url": "https://api.github.com/repos/o/r/compare/b...h" }`) }) got, _, err := client.Repositories.CompareCommits(context.Background(), "o", "r", "b", "h") if err != nil { t.Errorf("Repositories.CompareCommits returned error: %v", err) } want := &CommitsComparison{ BaseCommit: &RepositoryCommit{ SHA: String("s"), Commit: &Commit{ Author: &CommitAuthor{Name: String("n")}, Committer: &CommitAuthor{Name: String("n")}, Message: String("m"), Tree: &Tree{SHA: String("t")}, }, Author: &User{Login: String("l")}, Committer: &User{Login: String("l")}, Parents: []Commit{ { SHA: String("s"), }, }, }, Status: String("s"), AheadBy: Int(1), BehindBy: Int(2), TotalCommits: Int(1), Commits: []RepositoryCommit{ { SHA: String("s"), Commit: &Commit{ Author: &CommitAuthor{Name: String("n")}, }, Author: &User{Login: String("l")}, Committer: &User{Login: String("l")}, Parents: []Commit{ { SHA: String("s"), }, }, }, }, Files: []CommitFile{ { Filename: String("f"), }, }, HTMLURL: String("https://github.com/o/r/compare/b...h"), PermalinkURL: String("https://github.com/o/r/compare/o:bbcd538c8e72b8c175046e27cc8f907076331401...o:0328041d1152db8ae77652d1618a02e57f745f17"), DiffURL: String("https://github.com/o/r/compare/b...h.diff"), PatchURL: String("https://github.com/o/r/compare/b...h.patch"), URL: String("https://api.github.com/repos/o/r/compare/b...h"), } if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.CompareCommits returned \n%+v, want \n%+v", got, want) } } func TestRepositoriesService_ListBranchesHeadCommit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/commits/s/branches-where-head", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprintf(w, `[{"name": "b"}]`) }) branches, _, err := client.Repositories.ListBranchesHeadCommit(context.Background(), "o", "r", "s") if err != nil { t.Errorf("Repositories.ListBranchesHeadCommit returned error: %v", err) } want := []*BranchCommit{{Name: String("b")}} if !reflect.DeepEqual(branches, want) { t.Errorf("Repositories.ListBranchesHeadCommit returned %+v, want %+v", branches, want) } } go-github-28.1.1/github/repos_community_health.go000066400000000000000000000037431353501270500220720ustar00rootroot00000000000000// Copyright 2017 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "time" ) // Metric represents the different fields for one file in community health files. type Metric struct { Name *string `json:"name"` Key *string `json:"key"` URL *string `json:"url"` HTMLURL *string `json:"html_url"` } // CommunityHealthFiles represents the different files in the community health metrics response. type CommunityHealthFiles struct { CodeOfConduct *Metric `json:"code_of_conduct"` Contributing *Metric `json:"contributing"` IssueTemplate *Metric `json:"issue_template"` PullRequestTemplate *Metric `json:"pull_request_template"` License *Metric `json:"license"` Readme *Metric `json:"readme"` } // CommunityHealthMetrics represents a response containing the community metrics of a repository. type CommunityHealthMetrics struct { HealthPercentage *int `json:"health_percentage"` Files *CommunityHealthFiles `json:"files"` UpdatedAt *time.Time `json:"updated_at"` } // GetCommunityHealthMetrics retrieves all the community health metrics for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/community/#retrieve-community-health-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) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeRepositoryCommunityHealthMetricsPreview) metrics := &CommunityHealthMetrics{} resp, err := s.client.Do(ctx, req, metrics) if err != nil { return nil, resp, err } return metrics, resp, nil } go-github-28.1.1/github/repos_community_health_test.go000066400000000000000000000055761353501270500231370ustar00rootroot00000000000000// Copyright 2017 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" "reflect" "testing" "time" ) func TestRepositoriesService_GetCommunityHealthMetrics(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/community/profile", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeRepositoryCommunityHealthMetricsPreview) fmt.Fprintf(w, `{ "health_percentage": 100, "files": { "code_of_conduct": { "name": "Contributor Covenant", "key": "contributor_covenant", "url": null, "html_url": "https://github.com/octocat/Hello-World/blob/master/CODE_OF_CONDUCT.md" }, "contributing": { "url": "https://api.github.com/repos/octocat/Hello-World/contents/CONTRIBUTING", "html_url": "https://github.com/octocat/Hello-World/blob/master/CONTRIBUTING" }, "license": { "name": "MIT License", "key": "mit", "url": "https://api.github.com/licenses/mit", "html_url": "https://github.com/octocat/Hello-World/blob/master/LICENSE" }, "readme": { "url": "https://api.github.com/repos/octocat/Hello-World/contents/README.md", "html_url": "https://github.com/octocat/Hello-World/blob/master/README.md" } }, "updated_at": "2017-02-28T00:00:00Z" }`) }) got, _, err := client.Repositories.GetCommunityHealthMetrics(context.Background(), "o", "r") if err != nil { t.Errorf("Repositories.GetCommunityHealthMetrics returned error: %v", err) } updatedAt := time.Date(2017, time.February, 28, 0, 0, 0, 0, time.UTC) want := &CommunityHealthMetrics{ HealthPercentage: Int(100), UpdatedAt: &updatedAt, Files: &CommunityHealthFiles{ CodeOfConduct: &Metric{ Name: String("Contributor Covenant"), Key: String("contributor_covenant"), HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/CODE_OF_CONDUCT.md"), }, Contributing: &Metric{ URL: String("https://api.github.com/repos/octocat/Hello-World/contents/CONTRIBUTING"), HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/CONTRIBUTING"), }, License: &Metric{ Name: String("MIT License"), Key: String("mit"), URL: String("https://api.github.com/licenses/mit"), HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/LICENSE"), }, Readme: &Metric{ URL: String("https://api.github.com/repos/octocat/Hello-World/contents/README.md"), HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/README.md"), }, }, } if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.GetCommunityHealthMetrics:\ngot:\n%v\nwant:\n%v", Stringify(got), Stringify(want)) } } go-github-28.1.1/github/repos_contents.go000066400000000000000000000231731353501270500203550ustar00rootroot00000000000000// 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. // Repository contents API methods. // GitHub API docs: https://developer.github.com/v3/repos/contents/ package github import ( "context" "encoding/base64" "encoding/json" "fmt" "io" "net/http" "net/url" "path" ) // RepositoryContent represents a file or directory in a github repository. type RepositoryContent struct { Type *string `json:"type,omitempty"` // Target is only set if the type is "symlink" and the target is not a normal file. // If Target is set, Path will be the symlink path. Target *string `json:"target,omitempty"` Encoding *string `json:"encoding,omitempty"` Size *int `json:"size,omitempty"` Name *string `json:"name,omitempty"` Path *string `json:"path,omitempty"` // Content contains the actual file content, which may be encoded. // Callers should call GetContent which will decode the content if // necessary. Content *string `json:"content,omitempty"` SHA *string `json:"sha,omitempty"` URL *string `json:"url,omitempty"` GitURL *string `json:"git_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` DownloadURL *string `json:"download_url,omitempty"` } // RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile. type RepositoryContentResponse struct { Content *RepositoryContent `json:"content,omitempty"` Commit `json:"commit,omitempty"` } // RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile. type RepositoryContentFileOptions struct { Message *string `json:"message,omitempty"` Content []byte `json:"content,omitempty"` // unencoded SHA *string `json:"sha,omitempty"` Branch *string `json:"branch,omitempty"` Author *CommitAuthor `json:"author,omitempty"` Committer *CommitAuthor `json:"committer,omitempty"` } // RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA, // branch, or tag type RepositoryContentGetOptions struct { Ref string `url:"ref,omitempty"` } // String converts RepositoryContent to a string. It's primarily for testing. func (r RepositoryContent) String() string { return Stringify(r) } // GetContent returns the content of r, decoding it if necessary. func (r *RepositoryContent) GetContent() (string, error) { var encoding string if r.Encoding != nil { encoding = *r.Encoding } switch encoding { case "base64": c, err := base64.StdEncoding.DecodeString(*r.Content) return string(c), err case "": if r.Content == nil { return "", nil } return *r.Content, nil default: return "", fmt.Errorf("unsupported content encoding: %v", encoding) } } // GetReadme gets the Readme file for the repository. // // GitHub API docs: https://developer.github.com/v3/repos/contents/#get-the-readme func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string, opt *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) { u := fmt.Sprintf("repos/%v/%v/readme", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } readme := new(RepositoryContent) resp, err := s.client.Do(ctx, req, readme) if err != nil { return nil, resp, err } return readme, resp, nil } // DownloadContents returns an io.ReadCloser that reads the contents of the // specified file. This function will work with files of any size, as opposed // to GetContents which is limited to 1 Mb files. It is the caller's // responsibility to close the ReadCloser. func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo, filepath string, opt *RepositoryContentGetOptions) (io.ReadCloser, error) { dir := path.Dir(filepath) filename := path.Base(filepath) _, dirContents, _, err := s.GetContents(ctx, owner, repo, dir, opt) if err != nil { return nil, err } for _, contents := range dirContents { if *contents.Name == filename { if contents.DownloadURL == nil || *contents.DownloadURL == "" { return nil, fmt.Errorf("No download link found for %s", filepath) } resp, err := s.client.client.Get(*contents.DownloadURL) if err != nil { return nil, err } return resp.Body, nil } } return nil, fmt.Errorf("No file named %s found in %s", filename, dir) } // GetContents can return either the metadata and content of a single file // (when path references a file) or the metadata of all the files and/or // subdirectories of a directory (when path references a directory). To make it // easy to distinguish between both result types and to mimic the API as much // as possible, both result types will be returned but only one will contain a // value and the other will be nil. // // GitHub API docs: https://developer.github.com/v3/repos/contents/#get-contents func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opt *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) { escapedPath := (&url.URL{Path: path}).String() u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath) u, err = addOptions(u, opt) if err != nil { return nil, nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, nil, err } var rawJSON json.RawMessage resp, err = s.client.Do(ctx, req, &rawJSON) if err != nil { return nil, nil, resp, err } fileUnmarshalError := json.Unmarshal(rawJSON, &fileContent) if fileUnmarshalError == nil { return fileContent, nil, resp, nil } directoryUnmarshalError := json.Unmarshal(rawJSON, &directoryContent) if directoryUnmarshalError == nil { return nil, directoryContent, resp, nil } return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s", fileUnmarshalError, directoryUnmarshalError) } // 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 func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, nil, err } createResponse := new(RepositoryContentResponse) resp, err := s.client.Do(ctx, req, createResponse) if err != nil { return nil, resp, err } return createResponse, resp, nil } // 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 func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, nil, err } updateResponse := new(RepositoryContentResponse) resp, err := s.client.Do(ctx, req, updateResponse) if err != nil { return nil, resp, err } return updateResponse, resp, nil } // DeleteFile deletes a file from a repository and returns the commit. // Requires the blob SHA of the file to be deleted. // // GitHub API docs: https://developer.github.com/v3/repos/contents/#delete-a-file func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) req, err := s.client.NewRequest("DELETE", u, opt) if err != nil { return nil, nil, err } deleteResponse := new(RepositoryContentResponse) resp, err := s.client.Do(ctx, req, deleteResponse) if err != nil { return nil, resp, err } return deleteResponse, resp, nil } // archiveFormat is used to define the archive type when calling GetArchiveLink. type archiveFormat string const ( // Tarball specifies an archive in gzipped tar format. Tarball archiveFormat = "tarball" // Zipball specifies an archive in zip format. Zipball archiveFormat = "zipball" ) // GetArchiveLink returns an URL to download a tarball or zipball archive for a // repository. The archiveFormat can be specified by either the github.Tarball // or github.Zipball constant. // // GitHub API docs: https://developer.github.com/v3/repos/contents/#get-archive-link func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo string, archiveformat archiveFormat, opt *RepositoryContentGetOptions) (*url.URL, *Response, error) { u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat) if opt != nil && opt.Ref != "" { u += fmt.Sprintf("/%s", opt.Ref) } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var resp *http.Response // Use http.DefaultTransport if no custom Transport is configured req = withContext(ctx, req) if s.client.client.Transport == nil { resp, err = http.DefaultTransport.RoundTrip(req) } else { resp, err = s.client.client.Transport.RoundTrip(req) } if err != nil { return nil, nil, err } resp.Body.Close() if resp.StatusCode != http.StatusFound { return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) } parsedURL, err := url.Parse(resp.Header.Get("Location")) return parsedURL, newResponse(resp), err } go-github-28.1.1/github/repos_contents_test.go000066400000000000000000000276771353501270500214310ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "io/ioutil" "net/http" "reflect" "testing" ) func TestRepositoryContent_GetContent(t *testing.T) { tests := []struct { encoding, content *string // input encoding and content want string // desired output wantErr bool // whether an error is expected }{ { encoding: String(""), content: String("hello"), want: "hello", wantErr: false, }, { encoding: nil, content: String("hello"), want: "hello", wantErr: false, }, { encoding: nil, content: nil, want: "", wantErr: false, }, { encoding: String("base64"), content: String("aGVsbG8="), want: "hello", wantErr: false, }, { encoding: String("bad"), content: String("aGVsbG8="), want: "", wantErr: true, }, } for _, tt := range tests { r := RepositoryContent{Encoding: tt.encoding, Content: tt.content} got, err := r.GetContent() if err != nil && !tt.wantErr { t.Errorf("RepositoryContent(%s, %s) returned unexpected error: %v", stringOrNil(tt.encoding), stringOrNil(tt.content), err) } if err == nil && tt.wantErr { t.Errorf("RepositoryContent(%s, %s) did not return unexpected error", stringOrNil(tt.encoding), stringOrNil(tt.content)) } if want := tt.want; got != want { t.Errorf("RepositoryContent.GetContent returned %+v, want %+v", got, want) } } } // stringOrNil converts a potentially null string pointer to string. // For non-nil input pointer, the returned string is enclosed in double-quotes. func stringOrNil(s *string) string { if s == nil { return "" } return fmt.Sprintf("%q", *s) } func TestRepositoriesService_GetReadme(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/readme", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{ "type": "file", "encoding": "base64", "size": 5362, "name": "README.md", "path": "README.md" }`) }) readme, _, err := client.Repositories.GetReadme(context.Background(), "o", "r", &RepositoryContentGetOptions{}) if err != nil { t.Errorf("Repositories.GetReadme returned error: %v", err) } want := &RepositoryContent{Type: String("file"), Name: String("README.md"), Size: Int(5362), Encoding: String("base64"), Path: String("README.md")} if !reflect.DeepEqual(readme, want) { t.Errorf("Repositories.GetReadme returned %+v, want %+v", readme, want) } } func TestRepositoriesService_DownloadContents_Success(t *testing.T) { client, mux, serverURL, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{ "type": "file", "name": "f", "download_url": "`+serverURL+baseURLPath+`/download/f" }]`) }) mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, "foo") }) r, err := client.Repositories.DownloadContents(context.Background(), "o", "r", "d/f", nil) if err != nil { t.Errorf("Repositories.DownloadContents returned error: %v", err) } bytes, err := ioutil.ReadAll(r) if err != nil { t.Errorf("Error reading response body: %v", err) } r.Close() if got, want := string(bytes), "foo"; got != want { t.Errorf("Repositories.DownloadContents returned %v, want %v", got, want) } } func TestRepositoriesService_DownloadContents_NoDownloadURL(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{ "type": "file", "name": "f", }]`) }) _, err := client.Repositories.DownloadContents(context.Background(), "o", "r", "d/f", nil) if err == nil { t.Errorf("Repositories.DownloadContents did not return expected error") } } func TestRepositoriesService_DownloadContents_NoFile(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[]`) }) _, err := client.Repositories.DownloadContents(context.Background(), "o", "r", "d/f", nil) if err == nil { t.Errorf("Repositories.DownloadContents did not return expected error") } } func TestRepositoriesService_GetContents_File(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{ "type": "file", "encoding": "base64", "size": 20678, "name": "LICENSE", "path": "LICENSE" }`) }) fileContents, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "p", &RepositoryContentGetOptions{}) if err != nil { t.Errorf("Repositories.GetContents returned error: %v", err) } want := &RepositoryContent{Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Encoding: String("base64"), Path: String("LICENSE")} if !reflect.DeepEqual(fileContents, want) { t.Errorf("Repositories.GetContents returned %+v, want %+v", fileContents, want) } } func TestRepositoriesService_GetContents_FilenameNeedsEscape(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/p#?%/中.go", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{}`) }) _, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "p#?%/中.go", &RepositoryContentGetOptions{}) if err != nil { t.Fatalf("Repositories.GetContents returned error: %v", err) } } func TestRepositoriesService_GetContents_DirectoryWithSpaces(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/some directory/file.go", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{}`) }) _, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "some directory/file.go", &RepositoryContentGetOptions{}) if err != nil { t.Fatalf("Repositories.GetContents returned error: %v", err) } } func TestRepositoriesService_GetContents_DirectoryWithPlusChars(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/some directory+name/file.go", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{}`) }) _, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "some directory+name/file.go", &RepositoryContentGetOptions{}) if err != nil { t.Fatalf("Repositories.GetContents returned error: %v", err) } } func TestRepositoriesService_GetContents_Directory(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{ "type": "dir", "name": "lib", "path": "lib" }, { "type": "file", "size": 20678, "name": "LICENSE", "path": "LICENSE" }]`) }) _, directoryContents, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "p", &RepositoryContentGetOptions{}) if err != nil { t.Errorf("Repositories.GetContents returned error: %v", err) } want := []*RepositoryContent{{Type: String("dir"), Name: String("lib"), Path: String("lib")}, {Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Path: String("LICENSE")}} if !reflect.DeepEqual(directoryContents, want) { t.Errorf("Repositories.GetContents_Directory returned %+v, want %+v", directoryContents, want) } } func TestRepositoriesService_CreateFile(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") fmt.Fprint(w, `{ "content":{ "name":"p" }, "commit":{ "message":"m", "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" } }`) }) message := "m" content := []byte("c") repositoryContentsOptions := &RepositoryContentFileOptions{ Message: &message, Content: content, Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, } createResponse, _, err := client.Repositories.CreateFile(context.Background(), "o", "r", "p", repositoryContentsOptions) if err != nil { t.Errorf("Repositories.CreateFile returned error: %v", err) } want := &RepositoryContentResponse{ Content: &RepositoryContent{Name: String("p")}, Commit: Commit{ Message: String("m"), SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), }, } if !reflect.DeepEqual(createResponse, want) { t.Errorf("Repositories.CreateFile returned %+v, want %+v", createResponse, want) } } func TestRepositoriesService_UpdateFile(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") fmt.Fprint(w, `{ "content":{ "name":"p" }, "commit":{ "message":"m", "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" } }`) }) message := "m" content := []byte("c") sha := "f5f369044773ff9c6383c087466d12adb6fa0828" repositoryContentsOptions := &RepositoryContentFileOptions{ Message: &message, Content: content, SHA: &sha, Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, } updateResponse, _, err := client.Repositories.UpdateFile(context.Background(), "o", "r", "p", repositoryContentsOptions) if err != nil { t.Errorf("Repositories.UpdateFile returned error: %v", err) } want := &RepositoryContentResponse{ Content: &RepositoryContent{Name: String("p")}, Commit: Commit{ Message: String("m"), SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), }, } if !reflect.DeepEqual(updateResponse, want) { t.Errorf("Repositories.UpdateFile returned %+v, want %+v", updateResponse, want) } } func TestRepositoriesService_DeleteFile(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") fmt.Fprint(w, `{ "content": null, "commit":{ "message":"m", "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" } }`) }) message := "m" sha := "f5f369044773ff9c6383c087466d12adb6fa0828" repositoryContentsOptions := &RepositoryContentFileOptions{ Message: &message, SHA: &sha, Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, } deleteResponse, _, err := client.Repositories.DeleteFile(context.Background(), "o", "r", "p", repositoryContentsOptions) if err != nil { t.Errorf("Repositories.DeleteFile returned error: %v", err) } want := &RepositoryContentResponse{ Content: nil, Commit: Commit{ Message: String("m"), SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), }, } if !reflect.DeepEqual(deleteResponse, want) { t.Errorf("Repositories.DeleteFile returned %+v, want %+v", deleteResponse, want) } } func TestRepositoriesService_GetArchiveLink(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") http.Redirect(w, r, "http://github.com/a", http.StatusFound) }) url, resp, err := client.Repositories.GetArchiveLink(context.Background(), "o", "r", Tarball, &RepositoryContentGetOptions{}) if err != nil { t.Errorf("Repositories.GetArchiveLink returned error: %v", err) } if resp.StatusCode != http.StatusFound { t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound) } want := "http://github.com/a" if url.String() != want { t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want) } } go-github-28.1.1/github/repos_deployments.go000066400000000000000000000177401353501270500210660ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "strings" ) // Deployment represents a deployment in a repo type Deployment struct { URL *string `json:"url,omitempty"` ID *int64 `json:"id,omitempty"` SHA *string `json:"sha,omitempty"` Ref *string `json:"ref,omitempty"` Task *string `json:"task,omitempty"` Payload json.RawMessage `json:"payload,omitempty"` Environment *string `json:"environment,omitempty"` Description *string `json:"description,omitempty"` Creator *User `json:"creator,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` StatusesURL *string `json:"statuses_url,omitempty"` RepositoryURL *string `json:"repository_url,omitempty"` NodeID *string `json:"node_id,omitempty"` } // DeploymentRequest represents a deployment request type DeploymentRequest struct { Ref *string `json:"ref,omitempty"` Task *string `json:"task,omitempty"` AutoMerge *bool `json:"auto_merge,omitempty"` RequiredContexts *[]string `json:"required_contexts,omitempty"` Payload *string `json:"payload,omitempty"` Environment *string `json:"environment,omitempty"` Description *string `json:"description,omitempty"` TransientEnvironment *bool `json:"transient_environment,omitempty"` ProductionEnvironment *bool `json:"production_environment,omitempty"` } // DeploymentsListOptions specifies the optional parameters to the // RepositoriesService.ListDeployments method. type DeploymentsListOptions struct { // SHA of the Deployment. SHA string `url:"sha,omitempty"` // List deployments for a given ref. Ref string `url:"ref,omitempty"` // List deployments for a given task. Task string `url:"task,omitempty"` // List deployments for a given environment. Environment string `url:"environment,omitempty"` ListOptions } // ListDeployments lists the deployments of a repository. // // GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployments func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opt *DeploymentsListOptions) ([]*Deployment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var deployments []*Deployment resp, err := s.client.Do(ctx, req, &deployments) if err != nil { return nil, resp, err } return deployments, resp, nil } // GetDeployment returns a single deployment of a repository. // // GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Deployment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } deployment := new(Deployment) resp, err := s.client.Do(ctx, req, deployment) if err != nil { return nil, resp, err } return deployment, resp, nil } // CreateDeployment creates a new deployment for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo string, request *DeploymentRequest) (*Deployment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) req, err := s.client.NewRequest("POST", u, request) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) d := new(Deployment) resp, err := s.client.Do(ctx, req, d) if err != nil { return nil, resp, err } return d, resp, nil } // DeploymentStatus represents the status of a // particular deployment. type DeploymentStatus struct { ID *int64 `json:"id,omitempty"` // State is the deployment state. // Possible values are: "pending", "success", "failure", "error", "inactive". State *string `json:"state,omitempty"` Creator *User `json:"creator,omitempty"` Description *string `json:"description,omitempty"` TargetURL *string `json:"target_url,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` DeploymentURL *string `json:"deployment_url,omitempty"` RepositoryURL *string `json:"repository_url,omitempty"` NodeID *string `json:"node_id,omitempty"` } // DeploymentStatusRequest represents a deployment request type DeploymentStatusRequest struct { State *string `json:"state,omitempty"` LogURL *string `json:"log_url,omitempty"` Description *string `json:"description,omitempty"` Environment *string `json:"environment,omitempty"` EnvironmentURL *string `json:"environment_url,omitempty"` AutoInactive *bool `json:"auto_inactive,omitempty"` } // ListDeploymentStatuses lists the statuses of a given deployment of a repository. // // GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployment-statuses func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opt *ListOptions) ([]*DeploymentStatus, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var statuses []*DeploymentStatus resp, err := s.client.Do(ctx, req, &statuses) if err != nil { return nil, resp, err } return statuses, resp, nil } // GetDeploymentStatus returns a single deployment status of a repository. // // GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment-status func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, repo string, deploymentID, deploymentStatusID int64) (*DeploymentStatus, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses/%v", owner, repo, deploymentID, deploymentStatusID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) d := new(DeploymentStatus) resp, err := s.client.Do(ctx, req, d) if err != nil { return nil, resp, err } return d, resp, nil } // CreateDeploymentStatus creates a new status for a deployment. // // GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment-status func (s *RepositoriesService) CreateDeploymentStatus(ctx context.Context, owner, repo string, deployment int64, request *DeploymentStatusRequest) (*DeploymentStatus, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) req, err := s.client.NewRequest("POST", u, request) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) d := new(DeploymentStatus) resp, err := s.client.Do(ctx, req, d) if err != nil { return nil, resp, err } return d, resp, nil } go-github-28.1.1/github/repos_deployments_test.go000066400000000000000000000127561353501270500221270ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "strings" "testing" ) func TestRepositoriesService_ListDeployments(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/deployments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"environment": "test"}) fmt.Fprint(w, `[{"id":1}, {"id":2}]`) }) opt := &DeploymentsListOptions{Environment: "test"} deployments, _, err := client.Repositories.ListDeployments(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListDeployments returned error: %v", err) } want := []*Deployment{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(deployments, want) { t.Errorf("Repositories.ListDeployments returned %+v, want %+v", deployments, want) } } func TestRepositoriesService_GetDeployment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/deployments/3", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":3}`) }) deployment, _, err := client.Repositories.GetDeployment(context.Background(), "o", "r", 3) if err != nil { t.Errorf("Repositories.GetDeployment returned error: %v", err) } want := &Deployment{ID: Int64(3)} if !reflect.DeepEqual(deployment, want) { t.Errorf("Repositories.GetDeployment returned %+v, want %+v", deployment, want) } } func TestRepositoriesService_CreateDeployment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &DeploymentRequest{Ref: String("1111"), Task: String("deploy"), TransientEnvironment: Bool(true)} mux.HandleFunc("/repos/o/r/deployments", func(w http.ResponseWriter, r *http.Request) { v := new(DeploymentRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") wantAcceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"ref": "1111", "task": "deploy"}`) }) deployment, _, err := client.Repositories.CreateDeployment(context.Background(), "o", "r", input) if err != nil { t.Errorf("Repositories.CreateDeployment returned error: %v", err) } want := &Deployment{Ref: String("1111"), Task: String("deploy")} if !reflect.DeepEqual(deployment, want) { t.Errorf("Repositories.CreateDeployment returned %+v, want %+v", deployment, want) } } func TestRepositoriesService_ListDeploymentStatuses(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/deployments/1/statuses", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}, {"id":2}]`) }) opt := &ListOptions{Page: 2} statutses, _, err := client.Repositories.ListDeploymentStatuses(context.Background(), "o", "r", 1, opt) if err != nil { t.Errorf("Repositories.ListDeploymentStatuses returned error: %v", err) } want := []*DeploymentStatus{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(statutses, want) { t.Errorf("Repositories.ListDeploymentStatuses returned %+v, want %+v", statutses, want) } } func TestRepositoriesService_GetDeploymentStatus(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} mux.HandleFunc("/repos/o/r/deployments/3/statuses/4", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `{"id":4}`) }) deploymentStatus, _, err := client.Repositories.GetDeploymentStatus(context.Background(), "o", "r", 3, 4) if err != nil { t.Errorf("Repositories.GetDeploymentStatus returned error: %v", err) } want := &DeploymentStatus{ID: Int64(4)} if !reflect.DeepEqual(deploymentStatus, want) { t.Errorf("Repositories.GetDeploymentStatus returned %+v, want %+v", deploymentStatus, want) } } func TestRepositoriesService_CreateDeploymentStatus(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &DeploymentStatusRequest{State: String("inactive"), Description: String("deploy"), AutoInactive: Bool(false)} mux.HandleFunc("/repos/o/r/deployments/1/statuses", func(w http.ResponseWriter, r *http.Request) { v := new(DeploymentStatusRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") wantAcceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"state": "inactive", "description": "deploy"}`) }) deploymentStatus, _, err := client.Repositories.CreateDeploymentStatus(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Repositories.CreateDeploymentStatus returned error: %v", err) } want := &DeploymentStatus{State: String("inactive"), Description: String("deploy")} if !reflect.DeepEqual(deploymentStatus, want) { t.Errorf("Repositories.CreateDeploymentStatus returned %+v, want %+v", deploymentStatus, want) } } go-github-28.1.1/github/repos_forks.go000066400000000000000000000054641353501270500176470ustar00rootroot00000000000000// 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" "encoding/json" ) // RepositoryListForksOptions specifies the optional parameters to the // RepositoriesService.ListForks method. type RepositoryListForksOptions struct { // How to sort the forks list. Possible values are: newest, oldest, // watchers. Default is "newest". Sort string `url:"sort,omitempty"` ListOptions } // ListForks lists the forks of the specified repository. // // GitHub API docs: https://developer.github.com/v3/repos/forks/#list-forks func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, opt *RepositoryListForksOptions) ([]*Repository, *Response, error) { u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when topics API fully launches. req.Header.Set("Accept", mediaTypeTopicsPreview) var repos []*Repository resp, err := s.client.Do(ctx, req, &repos) if err != nil { return nil, resp, err } return repos, resp, nil } // RepositoryCreateForkOptions specifies the optional parameters to the // RepositoriesService.CreateFork method. type RepositoryCreateForkOptions struct { // The organization to fork the repository into. Organization string `url:"organization,omitempty"` } // CreateFork creates a fork of the specified repository. // // This method might return an *AcceptedError and a status code of // 202. This is because this is the status that GitHub returns to signify that // it is now computing creating the fork in a background task. In this event, // the Repository value will be returned, which includes the details about the pending fork. // 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/forks/#create-a-fork func (s *RepositoriesService) CreateFork(ctx context.Context, owner, repo string, opt *RepositoryCreateForkOptions) (*Repository, *Response, error) { u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, nil, err } fork := new(Repository) resp, err := s.client.Do(ctx, req, fork) if err != nil { // Persist AcceptedError's metadata to the Repository object. if aerr, ok := err.(*AcceptedError); ok { if err := json.Unmarshal(aerr.Raw, fork); err != nil { return fork, resp, err } return fork, resp, err } return nil, resp, err } return fork, resp, nil } go-github-28.1.1/github/repos_forks_test.go000066400000000000000000000057751353501270500207130ustar00rootroot00000000000000// 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" "net/http" "reflect" "testing" ) func TestRepositoriesService_ListForks(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/forks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeTopicsPreview) testFormValues(t, r, values{ "sort": "newest", "page": "3", }) fmt.Fprint(w, `[{"id":1},{"id":2}]`) }) opt := &RepositoryListForksOptions{ Sort: "newest", ListOptions: ListOptions{Page: 3}, } repos, _, err := client.Repositories.ListForks(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListForks returned error: %v", err) } want := []*Repository{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(repos, want) { t.Errorf("Repositories.ListForks returned %+v, want %+v", repos, want) } } func TestRepositoriesService_ListForks_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.ListForks(context.Background(), "%", "r", nil) testURLParseError(t, err) } func TestRepositoriesService_CreateFork(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/forks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testFormValues(t, r, values{"organization": "o"}) fmt.Fprint(w, `{"id":1}`) }) opt := &RepositoryCreateForkOptions{Organization: "o"} repo, _, err := client.Repositories.CreateFork(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.CreateFork returned error: %v", err) } want := &Repository{ID: Int64(1)} if !reflect.DeepEqual(repo, want) { t.Errorf("Repositories.CreateFork returned %+v, want %+v", repo, want) } } func TestRepositoriesService_CreateFork_deferred(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/forks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testFormValues(t, r, values{"organization": "o"}) // This response indicates the fork will happen asynchronously. w.WriteHeader(http.StatusAccepted) fmt.Fprint(w, `{"id":1}`) }) opt := &RepositoryCreateForkOptions{Organization: "o"} repo, _, err := client.Repositories.CreateFork(context.Background(), "o", "r", opt) if _, ok := err.(*AcceptedError); !ok { t.Errorf("Repositories.CreateFork returned error: %v (want AcceptedError)", err) } want := &Repository{ID: Int64(1)} if !reflect.DeepEqual(repo, want) { t.Errorf("Repositories.CreateFork returned %+v, want %+v", repo, want) } } func TestRepositoriesService_CreateFork_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.CreateFork(context.Background(), "%", "r", nil) testURLParseError(t, err) } go-github-28.1.1/github/repos_hooks.go000066400000000000000000000161411353501270500176400ustar00rootroot00000000000000// 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" "time" ) // WebHookPayload represents the data that is received from GitHub when a push // event hook is triggered. The format of these payloads pre-date most of the // GitHub v3 API, so there are lots of minor incompatibilities with the types // defined in the rest of the API. Therefore, several types are duplicated // here to account for these differences. // // GitHub API docs: https://help.github.com/articles/post-receive-hooks type WebHookPayload struct { After *string `json:"after,omitempty"` Before *string `json:"before,omitempty"` Commits []WebHookCommit `json:"commits,omitempty"` Compare *string `json:"compare,omitempty"` Created *bool `json:"created,omitempty"` Deleted *bool `json:"deleted,omitempty"` Forced *bool `json:"forced,omitempty"` HeadCommit *WebHookCommit `json:"head_commit,omitempty"` Pusher *User `json:"pusher,omitempty"` Ref *string `json:"ref,omitempty"` Repo *Repository `json:"repository,omitempty"` Sender *User `json:"sender,omitempty"` } func (w WebHookPayload) String() string { return Stringify(w) } // WebHookCommit represents the commit variant we receive from GitHub in a // WebHookPayload. type WebHookCommit struct { Added []string `json:"added,omitempty"` Author *WebHookAuthor `json:"author,omitempty"` Committer *WebHookAuthor `json:"committer,omitempty"` Distinct *bool `json:"distinct,omitempty"` ID *string `json:"id,omitempty"` Message *string `json:"message,omitempty"` Modified []string `json:"modified,omitempty"` Removed []string `json:"removed,omitempty"` Timestamp *time.Time `json:"timestamp,omitempty"` } func (w WebHookCommit) String() string { return Stringify(w) } // WebHookAuthor represents the author or committer of a commit, as specified // in a WebHookCommit. The commit author may not correspond to a GitHub User. type WebHookAuthor struct { Email *string `json:"email,omitempty"` Name *string `json:"name,omitempty"` Username *string `json:"username,omitempty"` } func (w WebHookAuthor) String() string { return Stringify(w) } // Hook represents a GitHub (web and service) hook for a repository. type Hook struct { CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` URL *string `json:"url,omitempty"` ID *int64 `json:"id,omitempty"` // Only the following fields are used when creating a hook. // Config is required. Config map[string]interface{} `json:"config,omitempty"` Events []string `json:"events,omitempty"` Active *bool `json:"active,omitempty"` } func (h Hook) String() string { return Stringify(h) } // createHookRequest is a subset of Hook and is used internally // by CreateHook to pass only the known fields for the endpoint. // // See https://github.com/google/go-github/issues/1015 for more // information. type createHookRequest struct { // Config is required. Name string `json:"name"` Config map[string]interface{} `json:"config,omitempty"` Events []string `json:"events,omitempty"` Active *bool `json:"active,omitempty"` } // CreateHook creates a Hook for the specified repository. // Config is a required field. // // Note that only a subset of the hook fields are used and hook must // not be nil. // // GitHub API docs: https://developer.github.com/v3/repos/hooks/#create-a-hook func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) { u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) hookReq := &createHookRequest{ Name: "web", Events: hook.Events, Active: hook.Active, Config: hook.Config, } req, err := s.client.NewRequest("POST", u, hookReq) if err != nil { return nil, nil, err } h := new(Hook) resp, err := s.client.Do(ctx, req, h) if err != nil { return nil, resp, err } return h, resp, nil } // ListHooks lists all Hooks for the specified repository. // // GitHub API docs: https://developer.github.com/v3/repos/hooks/#list func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Hook, *Response, error) { u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var hooks []*Hook resp, err := s.client.Do(ctx, req, &hooks) if err != nil { return nil, resp, err } return hooks, resp, nil } // GetHook returns a single specified Hook. // // GitHub API docs: https://developer.github.com/v3/repos/hooks/#get-single-hook func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) { u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } h := new(Hook) resp, err := s.client.Do(ctx, req, h) if err != nil { return nil, resp, err } return h, resp, nil } // EditHook updates a specified Hook. // // GitHub API docs: https://developer.github.com/v3/repos/hooks/#edit-a-hook func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) { u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) req, err := s.client.NewRequest("PATCH", u, hook) if err != nil { return nil, nil, err } h := new(Hook) resp, err := s.client.Do(ctx, req, h) if err != nil { return nil, resp, err } return h, resp, nil } // DeleteHook deletes a specified Hook. // // GitHub API docs: https://developer.github.com/v3/repos/hooks/#delete-a-hook func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // PingHook triggers a 'ping' event to be sent to the Hook. // // GitHub API docs: https://developer.github.com/v3/repos/hooks/#ping-a-hook func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // TestHook triggers a test Hook by github. // // GitHub API docs: https://developer.github.com/v3/repos/hooks/#test-a-push-hook func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/repos_hooks_test.go000066400000000000000000000123731353501270500207020ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestRepositoriesService_CreateHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Hook{CreatedAt: &referenceTime} mux.HandleFunc("/repos/o/r/hooks", func(w http.ResponseWriter, r *http.Request) { v := new(createHookRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := &createHookRequest{Name: "web"} if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"id":1}`) }) hook, _, err := client.Repositories.CreateHook(context.Background(), "o", "r", input) if err != nil { t.Errorf("Repositories.CreateHook returned error: %v", err) } want := &Hook{ID: Int64(1)} if !reflect.DeepEqual(hook, want) { t.Errorf("Repositories.CreateHook returned %+v, want %+v", hook, want) } } func TestRepositoriesService_ListHooks(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/hooks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}, {"id":2}]`) }) opt := &ListOptions{Page: 2} hooks, _, err := client.Repositories.ListHooks(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListHooks returned error: %v", err) } want := []*Hook{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(hooks, want) { t.Errorf("Repositories.ListHooks returned %+v, want %+v", hooks, want) } } func TestRepositoriesService_ListHooks_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.ListHooks(context.Background(), "%", "%", nil) testURLParseError(t, err) } func TestRepositoriesService_GetHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/hooks/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) hook, _, err := client.Repositories.GetHook(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.GetHook returned error: %v", err) } want := &Hook{ID: Int64(1)} if !reflect.DeepEqual(hook, want) { t.Errorf("Repositories.GetHook returned %+v, want %+v", hook, want) } } func TestRepositoriesService_GetHook_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.GetHook(context.Background(), "%", "%", 1) testURLParseError(t, err) } func TestRepositoriesService_EditHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Hook{} mux.HandleFunc("/repos/o/r/hooks/1", func(w http.ResponseWriter, r *http.Request) { v := new(Hook) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) hook, _, err := client.Repositories.EditHook(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Repositories.EditHook returned error: %v", err) } want := &Hook{ID: Int64(1)} if !reflect.DeepEqual(hook, want) { t.Errorf("Repositories.EditHook returned %+v, want %+v", hook, want) } } func TestRepositoriesService_EditHook_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.EditHook(context.Background(), "%", "%", 1, nil) testURLParseError(t, err) } func TestRepositoriesService_DeleteHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/hooks/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Repositories.DeleteHook(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.DeleteHook returned error: %v", err) } } func TestRepositoriesService_DeleteHook_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Repositories.DeleteHook(context.Background(), "%", "%", 1) testURLParseError(t, err) } func TestRepositoriesService_PingHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/hooks/1/pings", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") }) _, err := client.Repositories.PingHook(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.PingHook returned error: %v", err) } } func TestRepositoriesService_TestHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/hooks/1/tests", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") }) _, err := client.Repositories.TestHook(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.TestHook returned error: %v", err) } } func TestRepositoriesService_TestHook_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Repositories.TestHook(context.Background(), "%", "%", 1) testURLParseError(t, err) } go-github-28.1.1/github/repos_invitations.go000066400000000000000000000056721353501270500210730ustar00rootroot00000000000000// 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" ) // RepositoryInvitation represents an invitation to collaborate on a repo. type RepositoryInvitation struct { ID *int64 `json:"id,omitempty"` Repo *Repository `json:"repository,omitempty"` Invitee *User `json:"invitee,omitempty"` Inviter *User `json:"inviter,omitempty"` // Permissions represents the permissions that the associated user will have // on the repository. Possible values are: "read", "write", "admin". Permissions *string `json:"permissions,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` } // ListInvitations lists all currently-open repository invitations. // // GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) { u := fmt.Sprintf("repos/%v/%v/invitations", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } invites := []*RepositoryInvitation{} resp, err := s.client.Do(ctx, req, &invites) if err != nil { return nil, resp, err } return invites, resp, nil } // DeleteInvitation deletes a repository invitation. // // GitHub API docs: https://developer.github.com/v3/repos/invitations/#delete-a-repository-invitation func (s *RepositoriesService) DeleteInvitation(ctx context.Context, owner, repo string, invitationID int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // UpdateInvitation updates the permissions associated with a repository // invitation. // // permissions represents the permissions that the associated user will have // on the repository. Possible values are: "read", "write", "admin". // // GitHub API docs: https://developer.github.com/v3/repos/invitations/#update-a-repository-invitation func (s *RepositoriesService) UpdateInvitation(ctx context.Context, owner, repo string, invitationID int64, permissions string) (*RepositoryInvitation, *Response, error) { opts := &struct { Permissions string `json:"permissions"` }{Permissions: permissions} u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID) req, err := s.client.NewRequest("PATCH", u, opts) if err != nil { return nil, nil, err } invite := &RepositoryInvitation{} resp, err := s.client.Do(ctx, req, invite) if err != nil { return nil, resp, err } return invite, resp, nil } go-github-28.1.1/github/repos_invitations_test.go000066400000000000000000000037511353501270500221260ustar00rootroot00000000000000// 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" "reflect" "testing" ) func TestRepositoriesService_ListInvitations(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/invitations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprintf(w, `[{"id":1}, {"id":2}]`) }) opt := &ListOptions{Page: 2} got, _, err := client.Repositories.ListInvitations(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListInvitations returned error: %v", err) } want := []*RepositoryInvitation{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ListInvitations = %+v, want %+v", got, want) } } func TestRepositoriesService_DeleteInvitation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/invitations/2", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Repositories.DeleteInvitation(context.Background(), "o", "r", 2) if err != nil { t.Errorf("Repositories.DeleteInvitation returned error: %v", err) } } func TestRepositoriesService_UpdateInvitation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/invitations/2", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") fmt.Fprintf(w, `{"id":1}`) }) got, _, err := client.Repositories.UpdateInvitation(context.Background(), "o", "r", 2, "write") if err != nil { t.Errorf("Repositories.UpdateInvitation returned error: %v", err) } want := &RepositoryInvitation{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.UpdateInvitation = %+v, want %+v", got, want) } } go-github-28.1.1/github/repos_keys.go000066400000000000000000000054061353501270500174720ustar00rootroot00000000000000// 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" ) // The Key type is defined in users_keys.go // ListKeys lists the deploy keys for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/keys/#list func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Key, *Response, error) { u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var keys []*Key resp, err := s.client.Do(ctx, req, &keys) if err != nil { return nil, resp, err } return keys, resp, nil } // GetKey fetches a single deploy key. // // GitHub API docs: https://developer.github.com/v3/repos/keys/#get 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) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } key := new(Key) resp, err := s.client.Do(ctx, req, key) if err != nil { return nil, resp, err } return key, resp, nil } // CreateKey adds a deploy key for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/keys/#create 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) req, err := s.client.NewRequest("POST", 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 } // 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 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) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/repos_keys_test.go000066400000000000000000000106311353501270500205250ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestRepositoriesService_ListKeys(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/keys", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} keys, _, err := client.Repositories.ListKeys(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListKeys returned error: %v", err) } want := []*Key{{ID: Int64(1)}} if !reflect.DeepEqual(keys, want) { t.Errorf("Repositories.ListKeys returned %+v, want %+v", keys, want) } } func TestRepositoriesService_ListKeys_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.ListKeys(context.Background(), "%", "%", nil) testURLParseError(t, err) } func TestRepositoriesService_GetKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/keys/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) key, _, err := client.Repositories.GetKey(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.GetKey returned error: %v", err) } want := &Key{ID: Int64(1)} if !reflect.DeepEqual(key, want) { t.Errorf("Repositories.GetKey returned %+v, want %+v", key, want) } } func TestRepositoriesService_GetKey_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.GetKey(context.Background(), "%", "%", 1) testURLParseError(t, err) } func TestRepositoriesService_CreateKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Key{Key: String("k"), Title: String("t")} mux.HandleFunc("/repos/o/r/keys", func(w http.ResponseWriter, r *http.Request) { v := new(Key) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) key, _, err := client.Repositories.CreateKey(context.Background(), "o", "r", input) if err != nil { t.Errorf("Repositories.GetKey returned error: %v", err) } want := &Key{ID: Int64(1)} if !reflect.DeepEqual(key, want) { t.Errorf("Repositories.GetKey returned %+v, want %+v", key, want) } } func TestRepositoriesService_CreateKey_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.CreateKey(context.Background(), "%", "%", nil) 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() mux.HandleFunc("/repos/o/r/keys/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Repositories.DeleteKey(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.DeleteKey returned error: %v", err) } } func TestRepositoriesService_DeleteKey_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Repositories.DeleteKey(context.Background(), "%", "%", 1) testURLParseError(t, err) } go-github-28.1.1/github/repos_merging.go000066400000000000000000000020631353501270500201430ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" ) // RepositoryMergeRequest represents a request to merge a branch in a // repository. type RepositoryMergeRequest struct { Base *string `json:"base,omitempty"` Head *string `json:"head,omitempty"` CommitMessage *string `json:"commit_message,omitempty"` } // Merge a branch in the specified repository. // // GitHub API docs: https://developer.github.com/v3/repos/merging/#perform-a-merge func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) { u := fmt.Sprintf("repos/%v/%v/merges", owner, repo) req, err := s.client.NewRequest("POST", u, request) if err != nil { return nil, nil, err } commit := new(RepositoryCommit) resp, err := s.client.Do(ctx, req, commit) if err != nil { return nil, resp, err } return commit, resp, nil } go-github-28.1.1/github/repos_merging_test.go000066400000000000000000000021621353501270500212020ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestRepositoriesService_Merge(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &RepositoryMergeRequest{ Base: String("b"), Head: String("h"), CommitMessage: String("c"), } mux.HandleFunc("/repos/o/r/merges", func(w http.ResponseWriter, r *http.Request) { v := new(RepositoryMergeRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"sha":"s"}`) }) commit, _, err := client.Repositories.Merge(context.Background(), "o", "r", input) if err != nil { t.Errorf("Repositories.Merge returned error: %v", err) } want := &RepositoryCommit{SHA: String("s")} if !reflect.DeepEqual(commit, want) { t.Errorf("Repositories.Merge returned %+v, want %+v", commit, want) } } go-github-28.1.1/github/repos_pages.go000066400000000000000000000135201353501270500176120ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "strings" ) // Pages represents a GitHub Pages site configuration. type Pages struct { URL *string `json:"url,omitempty"` Status *string `json:"status,omitempty"` CNAME *string `json:"cname,omitempty"` Custom404 *bool `json:"custom_404,omitempty"` HTMLURL *string `json:"html_url,omitempty"` Source *PagesSource `json:"source,omitempty"` } // PagesSource represents a GitHub page's source. type PagesSource struct { Branch *string `json:"branch,omitempty"` Path *string `json:"path,omitempty"` } // PagesError represents a build error for a GitHub Pages site. type PagesError struct { Message *string `json:"message,omitempty"` } // PagesBuild represents the build information for a GitHub Pages site. type PagesBuild struct { URL *string `json:"url,omitempty"` Status *string `json:"status,omitempty"` Error *PagesError `json:"error,omitempty"` Pusher *User `json:"pusher,omitempty"` Commit *string `json:"commit,omitempty"` Duration *int `json:"duration,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` } // EnablePages enables GitHub Pages for the named repo. // // GitHub API docs: https://developer.github.com/v3/repos/pages/#enable-a-pages-site func (s *RepositoriesService) EnablePages(ctx context.Context, owner, repo string) (*Pages, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeEnablePagesAPIPreview, mediaTypePagesPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) enable := new(Pages) resp, err := s.client.Do(ctx, req, enable) if err != nil { return nil, resp, err } return enable, resp, nil } // DisablePages disables GitHub Pages for the named repo. // // GitHub API docs: https://developer.github.com/v3/repos/pages/#disable-a-pages-site func (s *RepositoriesService) DisablePages(ctx context.Context, owner, repo string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview) return s.client.Do(ctx, req, nil) } // GetPagesInfo fetches information about a GitHub Pages site. // // GitHub API docs: https://developer.github.com/v3/repos/pages/#get-information-about-a-pages-site func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo string) (*Pages, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypePagesPreview) site := new(Pages) resp, err := s.client.Do(ctx, req, site) if err != nil { return nil, resp, err } return site, resp, nil } // ListPagesBuilds lists the builds for a GitHub Pages site. // // GitHub API docs: https://developer.github.com/v3/repos/pages/#list-pages-builds func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo string, opt *ListOptions) ([]*PagesBuild, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var pages []*PagesBuild resp, err := s.client.Do(ctx, req, &pages) if err != nil { return nil, resp, err } return pages, resp, nil } // 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 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) if err != nil { return nil, nil, err } build := new(PagesBuild) resp, err := s.client.Do(ctx, req, build) if err != nil { return nil, resp, err } return build, resp, nil } // 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 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) if err != nil { return nil, nil, err } build := new(PagesBuild) resp, err := s.client.Do(ctx, req, build) if err != nil { return nil, resp, err } return build, resp, nil } // RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit. // // GitHub API docs: https://developer.github.com/v3/repos/pages/#request-a-page-build func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypePagesPreview) build := new(PagesBuild) resp, err := s.client.Do(ctx, req, build) if err != nil { return nil, resp, err } return build, resp, nil } go-github-28.1.1/github/repos_pages_test.go000066400000000000000000000131511353501270500206510ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "net/http" "reflect" "strings" "testing" ) func TestRepositoriesService_EnablePages(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pages", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") wantAcceptHeaders := []string{mediaTypeEnablePagesAPIPreview, mediaTypePagesPreview} testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `{"url":"u","status":"s","cname":"c","custom_404":false,"html_url":"h", "source": {"branch":"master", "path":"/"}}`) }) page, _, err := client.Repositories.EnablePages(context.Background(), "o", "r") if err != nil { t.Errorf("Repositories.EnablePages returned error: %v", err) } want := &Pages{URL: String("u"), Status: String("s"), CNAME: String("c"), Custom404: Bool(false), HTMLURL: String("h"), Source: &PagesSource{Branch: String("master"), Path: String("/")}} if !reflect.DeepEqual(page, want) { t.Errorf("Repositories.EnablePages returned %v, want %v", page, want) } } func TestRepositoriesService_DisablePages(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pages", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeEnablePagesAPIPreview) }) _, err := client.Repositories.DisablePages(context.Background(), "o", "r") if err != nil { t.Errorf("Repositories.DisablePages returned error: %v", err) } } func TestRepositoriesService_GetPagesInfo(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pages", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypePagesPreview) fmt.Fprint(w, `{"url":"u","status":"s","cname":"c","custom_404":false,"html_url":"h"}`) }) page, _, err := client.Repositories.GetPagesInfo(context.Background(), "o", "r") if err != nil { t.Errorf("Repositories.GetPagesInfo returned error: %v", err) } want := &Pages{URL: String("u"), Status: String("s"), CNAME: String("c"), Custom404: Bool(false), HTMLURL: String("h")} if !reflect.DeepEqual(page, want) { t.Errorf("Repositories.GetPagesInfo returned %+v, want %+v", page, want) } } func TestRepositoriesService_ListPagesBuilds(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pages/builds", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"url":"u","status":"s","commit":"c"}]`) }) pages, _, err := client.Repositories.ListPagesBuilds(context.Background(), "o", "r", nil) if err != nil { t.Errorf("Repositories.ListPagesBuilds returned error: %v", err) } want := []*PagesBuild{{URL: String("u"), Status: String("s"), Commit: String("c")}} if !reflect.DeepEqual(pages, want) { t.Errorf("Repositories.ListPagesBuilds returned %+v, want %+v", pages, want) } } func TestRepositoriesService_ListPagesBuilds_withOptions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pages/builds", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `[]`) }) _, _, err := client.Repositories.ListPagesBuilds(context.Background(), "o", "r", &ListOptions{Page: 2}) if err != nil { t.Errorf("Repositories.ListPagesBuilds returned error: %v", err) } } func TestRepositoriesService_GetLatestPagesBuild(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pages/builds/latest", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"url":"u","status":"s","commit":"c"}`) }) build, _, err := client.Repositories.GetLatestPagesBuild(context.Background(), "o", "r") if err != nil { t.Errorf("Repositories.GetLatestPagesBuild returned error: %v", err) } want := &PagesBuild{URL: String("u"), Status: String("s"), Commit: String("c")} if !reflect.DeepEqual(build, want) { t.Errorf("Repositories.GetLatestPagesBuild returned %+v, want %+v", build, want) } } func TestRepositoriesService_GetPageBuild(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pages/builds/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"url":"u","status":"s","commit":"c"}`) }) build, _, err := client.Repositories.GetPageBuild(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.GetPageBuild returned error: %v", err) } want := &PagesBuild{URL: String("u"), Status: String("s"), Commit: String("c")} if !reflect.DeepEqual(build, want) { t.Errorf("Repositories.GetPageBuild returned %+v, want %+v", build, want) } } func TestRepositoriesService_RequestPageBuild(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pages/builds", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypePagesPreview) fmt.Fprint(w, `{"url":"u","status":"s"}`) }) build, _, err := client.Repositories.RequestPageBuild(context.Background(), "o", "r") if err != nil { t.Errorf("Repositories.RequestPageBuild returned error: %v", err) } want := &PagesBuild{URL: String("u"), Status: String("s")} if !reflect.DeepEqual(build, want) { t.Errorf("Repositories.RequestPageBuild returned %+v, want %+v", build, want) } } go-github-28.1.1/github/repos_prereceive_hooks.go000066400000000000000000000070631353501270500220540ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" ) // PreReceiveHook represents a GitHub pre-receive hook for a repository. type PreReceiveHook struct { ID *int64 `json:"id,omitempty"` Name *string `json:"name,omitempty"` Enforcement *string `json:"enforcement,omitempty"` ConfigURL *string `json:"configuration_url,omitempty"` } func (p PreReceiveHook) String() string { return Stringify(p) } // ListPreReceiveHooks lists all pre-receive hooks for the specified repository. // // GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#list-pre-receive-hooks func (s *RepositoriesService) ListPreReceiveHooks(ctx context.Context, owner, repo string, opt *ListOptions) ([]*PreReceiveHook, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) var hooks []*PreReceiveHook resp, err := s.client.Do(ctx, req, &hooks) if err != nil { return nil, resp, err } return hooks, resp, nil } // GetPreReceiveHook returns a single specified pre-receive hook. // // GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#get-a-single-pre-receive-hook func (s *RepositoriesService) GetPreReceiveHook(ctx context.Context, owner, repo string, id int64) (*PreReceiveHook, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) h := new(PreReceiveHook) resp, err := s.client.Do(ctx, req, h) if err != nil { return nil, resp, err } return h, resp, nil } // UpdatePreReceiveHook updates a specified pre-receive hook. // // GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#update-pre-receive-hook-enforcement func (s *RepositoriesService) UpdatePreReceiveHook(ctx context.Context, owner, repo string, id int64, hook *PreReceiveHook) (*PreReceiveHook, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) req, err := s.client.NewRequest("PATCH", u, hook) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) h := new(PreReceiveHook) resp, err := s.client.Do(ctx, req, h) if err != nil { return nil, resp, err } return h, resp, nil } // DeletePreReceiveHook deletes a specified pre-receive hook. // // GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#remove-enforcement-overrides-for-a-pre-receive-hook func (s *RepositoriesService) DeletePreReceiveHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/repos_prereceive_hooks_test.go000066400000000000000000000076331353501270500231160ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestRepositoriesService_ListPreReceiveHooks(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pre-receive-hooks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypePreReceiveHooksPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}, {"id":2}]`) }) opt := &ListOptions{Page: 2} hooks, _, err := client.Repositories.ListPreReceiveHooks(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListHooks returned error: %v", err) } want := []*PreReceiveHook{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(hooks, want) { t.Errorf("Repositories.ListPreReceiveHooks returned %+v, want %+v", hooks, want) } } func TestRepositoriesService_ListPreReceiveHooks_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.ListPreReceiveHooks(context.Background(), "%", "%", nil) testURLParseError(t, err) } func TestRepositoriesService_GetPreReceiveHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pre-receive-hooks/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypePreReceiveHooksPreview) fmt.Fprint(w, `{"id":1}`) }) hook, _, err := client.Repositories.GetPreReceiveHook(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.GetPreReceiveHook returned error: %v", err) } want := &PreReceiveHook{ID: Int64(1)} if !reflect.DeepEqual(hook, want) { t.Errorf("Repositories.GetPreReceiveHook returned %+v, want %+v", hook, want) } } func TestRepositoriesService_GetPreReceiveHook_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.GetPreReceiveHook(context.Background(), "%", "%", 1) testURLParseError(t, err) } func TestRepositoriesService_UpdatePreReceiveHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &PreReceiveHook{} mux.HandleFunc("/repos/o/r/pre-receive-hooks/1", func(w http.ResponseWriter, r *http.Request) { v := new(PreReceiveHook) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) hook, _, err := client.Repositories.UpdatePreReceiveHook(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Repositories.UpdatePreReceiveHook returned error: %v", err) } want := &PreReceiveHook{ID: Int64(1)} if !reflect.DeepEqual(hook, want) { t.Errorf("Repositories.UpdatePreReceiveHook returned %+v, want %+v", hook, want) } } func TestRepositoriesService_PreReceiveHook_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.UpdatePreReceiveHook(context.Background(), "%", "%", 1, nil) testURLParseError(t, err) } func TestRepositoriesService_DeletePreReceiveHook(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/pre-receive-hooks/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Repositories.DeletePreReceiveHook(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.DeletePreReceiveHook returned error: %v", err) } } func TestRepositoriesService_DeletePreReceiveHook_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Repositories.DeletePreReceiveHook(context.Background(), "%", "%", 1) testURLParseError(t, err) } go-github-28.1.1/github/repos_projects.go000066400000000000000000000037471353501270500203560ustar00rootroot00000000000000// Copyright 2017 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" ) // ProjectListOptions specifies the optional parameters to the // OrganizationsService.ListProjects and RepositoriesService.ListProjects methods. type ProjectListOptions struct { // Indicates the state of the projects to return. Can be either open, closed, or all. Default: open State string `url:"state,omitempty"` ListOptions } // ListProjects lists the projects for a repo. // // GitHub API docs: https://developer.github.com/v3/projects/#list-repository-projects func (s *RepositoriesService) ListProjects(ctx context.Context, owner, repo string, opt *ProjectListOptions) ([]*Project, *Response, error) { u := fmt.Sprintf("repos/%v/%v/projects", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. req.Header.Set("Accept", mediaTypeProjectsPreview) var projects []*Project resp, err := s.client.Do(ctx, req, &projects) if err != nil { return nil, resp, err } return projects, resp, nil } // CreateProject creates a GitHub Project for the specified repository. // // GitHub API docs: https://developer.github.com/v3/projects/#create-a-repository-project func (s *RepositoriesService) CreateProject(ctx context.Context, owner, repo string, opt *ProjectOptions) (*Project, *Response, error) { u := fmt.Sprintf("repos/%v/%v/projects", owner, repo) req, err := s.client.NewRequest("POST", u, opt) if err != nil { return nil, nil, err } // TODO: remove custom Accept headers when APIs fully launch. req.Header.Set("Accept", mediaTypeProjectsPreview) project := &Project{} resp, err := s.client.Do(ctx, req, project) if err != nil { return nil, resp, err } return project, resp, nil } go-github-28.1.1/github/repos_projects_test.go000066400000000000000000000036041353501270500214050ustar00rootroot00000000000000// Copyright 2017 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestRepositoriesService_ListProjects(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/projects", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeProjectsPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ProjectListOptions{ListOptions: ListOptions{Page: 2}} projects, _, err := client.Repositories.ListProjects(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListProjects returned error: %v", err) } want := []*Project{{ID: Int64(1)}} if !reflect.DeepEqual(projects, want) { t.Errorf("Repositories.ListProjects returned %+v, want %+v", projects, want) } } func TestRepositoriesService_CreateProject(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ProjectOptions{Name: String("Project Name"), Body: String("Project body.")} mux.HandleFunc("/repos/o/r/projects", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeProjectsPreview) v := &ProjectOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) project, _, err := client.Repositories.CreateProject(context.Background(), "o", "r", input) if err != nil { t.Errorf("Repositories.CreateProject returned error: %v", err) } want := &Project{ID: Int64(1)} if !reflect.DeepEqual(project, want) { t.Errorf("Repositories.CreateProject returned %+v, want %+v", project, want) } } go-github-28.1.1/github/repos_releases.go000066400000000000000000000306701353501270500203230ustar00rootroot00000000000000// 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" "errors" "fmt" "io" "mime" "net/http" "os" "path/filepath" "strings" ) // RepositoryRelease represents a GitHub release in a repository. type RepositoryRelease struct { TagName *string `json:"tag_name,omitempty"` TargetCommitish *string `json:"target_commitish,omitempty"` Name *string `json:"name,omitempty"` Body *string `json:"body,omitempty"` Draft *bool `json:"draft,omitempty"` Prerelease *bool `json:"prerelease,omitempty"` // The following fields are not used in CreateRelease or EditRelease: ID *int64 `json:"id,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` PublishedAt *Timestamp `json:"published_at,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` AssetsURL *string `json:"assets_url,omitempty"` Assets []ReleaseAsset `json:"assets,omitempty"` UploadURL *string `json:"upload_url,omitempty"` ZipballURL *string `json:"zipball_url,omitempty"` TarballURL *string `json:"tarball_url,omitempty"` Author *User `json:"author,omitempty"` NodeID *string `json:"node_id,omitempty"` } func (r RepositoryRelease) String() string { return Stringify(r) } // ReleaseAsset represents a GitHub release asset in a repository. type ReleaseAsset struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` Name *string `json:"name,omitempty"` Label *string `json:"label,omitempty"` State *string `json:"state,omitempty"` ContentType *string `json:"content_type,omitempty"` Size *int `json:"size,omitempty"` DownloadCount *int `json:"download_count,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` BrowserDownloadURL *string `json:"browser_download_url,omitempty"` Uploader *User `json:"uploader,omitempty"` NodeID *string `json:"node_id,omitempty"` } func (r ReleaseAsset) String() string { return Stringify(r) } // ListReleases lists the releases for a repository. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var releases []*RepositoryRelease resp, err := s.client.Do(ctx, req, &releases) if err != nil { return nil, resp, err } return releases, resp, nil } // GetRelease fetches a single release. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release func (s *RepositoriesService) GetRelease(ctx context.Context, owner, repo string, id int64) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) return s.getSingleRelease(ctx, u) } // GetLatestRelease fetches the latest published release for the repository. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#get-the-latest-release func (s *RepositoriesService) GetLatestRelease(ctx context.Context, owner, repo string) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/latest", owner, repo) return s.getSingleRelease(ctx, u) } // GetReleaseByTag fetches a release with the specified tag. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-release-by-tag-name func (s *RepositoriesService) GetReleaseByTag(ctx context.Context, owner, repo, tag string) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/tags/%s", owner, repo, tag) return s.getSingleRelease(ctx, u) } func (s *RepositoriesService) getSingleRelease(ctx context.Context, url string) (*RepositoryRelease, *Response, error) { req, err := s.client.NewRequest("GET", url, nil) if err != nil { return nil, nil, err } release := new(RepositoryRelease) resp, err := s.client.Do(ctx, req, release) if err != nil { return nil, resp, err } return release, resp, nil } // repositoryReleaseRequest is a subset of RepositoryRelease and // is used internally by CreateRelease and EditRelease to pass // only the known fields for these endpoints. // // See https://github.com/google/go-github/issues/992 for more // information. type repositoryReleaseRequest struct { TagName *string `json:"tag_name,omitempty"` TargetCommitish *string `json:"target_commitish,omitempty"` Name *string `json:"name,omitempty"` Body *string `json:"body,omitempty"` Draft *bool `json:"draft,omitempty"` Prerelease *bool `json:"prerelease,omitempty"` } // CreateRelease adds a new release for a repository. // // Note that only a subset of the release fields are used. // See RepositoryRelease for more information. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#create-a-release func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo string, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) releaseReq := &repositoryReleaseRequest{ TagName: release.TagName, TargetCommitish: release.TargetCommitish, Name: release.Name, Body: release.Body, Draft: release.Draft, Prerelease: release.Prerelease, } req, err := s.client.NewRequest("POST", u, releaseReq) if err != nil { return nil, nil, err } r := new(RepositoryRelease) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // EditRelease edits a repository release. // // Note that only a subset of the release fields are used. // See RepositoryRelease for more information. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo string, id int64, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) releaseReq := &repositoryReleaseRequest{ TagName: release.TagName, TargetCommitish: release.TargetCommitish, Name: release.Name, Body: release.Body, Draft: release.Draft, Prerelease: release.Prerelease, } req, err := s.client.NewRequest("PATCH", u, releaseReq) if err != nil { return nil, nil, err } r := new(RepositoryRelease) resp, err := s.client.Do(ctx, req, r) if err != nil { return nil, resp, err } return r, resp, nil } // DeleteRelease delete a single release from a repository. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#delete-a-release func (s *RepositoriesService) DeleteRelease(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // ListReleaseAssets lists the release's assets. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#list-assets-for-a-release func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*ReleaseAsset, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var assets []*ReleaseAsset resp, err := s.client.Do(ctx, req, &assets) if err != nil { return nil, resp, err } return assets, resp, nil } // GetReleaseAsset fetches a single release asset. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release-asset func (s *RepositoriesService) GetReleaseAsset(ctx context.Context, owner, repo string, id int64) (*ReleaseAsset, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } asset := new(ReleaseAsset) resp, err := s.client.Do(ctx, req, asset) if err != nil { return nil, resp, err } return asset, resp, nil } // DownloadReleaseAsset downloads a release asset or returns a redirect URL. // // DownloadReleaseAsset returns an io.ReadCloser that reads the contents of the // specified release asset. It is the caller's responsibility to close the ReadCloser. // If a redirect is returned, the redirect URL will be returned as a string instead // of the io.ReadCloser. Exactly one of rc and redirectURL will be zero. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release-asset func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, repo string, id int64) (rc io.ReadCloser, redirectURL string, err error) { u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, "", err } req.Header.Set("Accept", defaultMediaType) s.client.clientMu.Lock() defer s.client.clientMu.Unlock() var loc string saveRedirect := s.client.client.CheckRedirect s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { loc = req.URL.String() return errors.New("disable redirect") } defer func() { s.client.client.CheckRedirect = saveRedirect }() req = withContext(ctx, req) resp, err := s.client.client.Do(req) if err != nil { if !strings.Contains(err.Error(), "disable redirect") { return nil, "", err } return nil, loc, nil // Intentionally return no error with valid redirect URL. } if err := CheckResponse(resp); err != nil { resp.Body.Close() return nil, "", err } return resp.Body, "", nil } // EditReleaseAsset edits a repository release asset. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release-asset func (s *RepositoriesService) EditReleaseAsset(ctx context.Context, owner, repo string, id int64, release *ReleaseAsset) (*ReleaseAsset, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) req, err := s.client.NewRequest("PATCH", u, release) if err != nil { return nil, nil, err } asset := new(ReleaseAsset) resp, err := s.client.Do(ctx, req, asset) if err != nil { return nil, resp, err } return asset, resp, nil } // DeleteReleaseAsset delete a single release asset from a repository. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#delete-a-release-asset func (s *RepositoriesService) DeleteReleaseAsset(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // UploadReleaseAsset creates an asset by uploading a file into a release repository. // To upload assets that cannot be represented by an os.File, call NewUploadRequest directly. // // GitHub API docs: https://developer.github.com/v3/repos/releases/#upload-a-release-asset func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, repo string, id int64, opt *UploadOptions, file *os.File) (*ReleaseAsset, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } stat, err := file.Stat() if err != nil { return nil, nil, err } if stat.IsDir() { return nil, nil, errors.New("the asset to upload can't be a directory") } mediaType := mime.TypeByExtension(filepath.Ext(file.Name())) if opt.MediaType != "" { mediaType = opt.MediaType } req, err := s.client.NewUploadRequest(u, file, stat.Size(), mediaType) if err != nil { return nil, nil, err } asset := new(ReleaseAsset) resp, err := s.client.Do(ctx, req, asset) if err != nil { return nil, resp, err } return asset, resp, nil } go-github-28.1.1/github/repos_releases_test.go000066400000000000000000000323421353501270500213600ustar00rootroot00000000000000// 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 ( "bytes" "context" "encoding/json" "fmt" "io/ioutil" "net/http" "os" "reflect" "strings" "testing" ) func TestRepositoriesService_ListReleases(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} releases, _, err := client.Repositories.ListReleases(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListReleases returned error: %v", err) } want := []*RepositoryRelease{{ID: Int64(1)}} if !reflect.DeepEqual(releases, want) { t.Errorf("Repositories.ListReleases returned %+v, want %+v", releases, want) } } func TestRepositoriesService_GetRelease(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1,"author":{"login":"l"}}`) }) release, resp, err := client.Repositories.GetRelease(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.GetRelease returned error: %v\n%v", err, resp.Body) } want := &RepositoryRelease{ID: Int64(1), Author: &User{Login: String("l")}} if !reflect.DeepEqual(release, want) { t.Errorf("Repositories.GetRelease returned %+v, want %+v", release, want) } } func TestRepositoriesService_GetLatestRelease(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases/latest", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":3}`) }) release, resp, err := client.Repositories.GetLatestRelease(context.Background(), "o", "r") if err != nil { t.Errorf("Repositories.GetLatestRelease returned error: %v\n%v", err, resp.Body) } want := &RepositoryRelease{ID: Int64(3)} if !reflect.DeepEqual(release, want) { t.Errorf("Repositories.GetLatestRelease returned %+v, want %+v", release, want) } } func TestRepositoriesService_GetReleaseByTag(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases/tags/foo", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":13}`) }) release, resp, err := client.Repositories.GetReleaseByTag(context.Background(), "o", "r", "foo") if err != nil { t.Errorf("Repositories.GetReleaseByTag returned error: %v\n%v", err, resp.Body) } want := &RepositoryRelease{ID: Int64(13)} if !reflect.DeepEqual(release, want) { t.Errorf("Repositories.GetReleaseByTag returned %+v, want %+v", release, want) } } func TestRepositoriesService_CreateRelease(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &RepositoryRelease{ Name: String("v1.0"), // Fields to be removed: ID: Int64(2), CreatedAt: &Timestamp{referenceTime}, PublishedAt: &Timestamp{referenceTime}, URL: String("http://url/"), HTMLURL: String("http://htmlurl/"), AssetsURL: String("http://assetsurl/"), Assets: []ReleaseAsset{{ID: Int64(5)}}, UploadURL: String("http://uploadurl/"), ZipballURL: String("http://zipballurl/"), TarballURL: String("http://tarballurl/"), Author: &User{Name: String("octocat")}, NodeID: String("nodeid"), } mux.HandleFunc("/repos/o/r/releases", func(w http.ResponseWriter, r *http.Request) { v := new(repositoryReleaseRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") want := &repositoryReleaseRequest{Name: String("v1.0")} if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"id":1}`) }) release, _, err := client.Repositories.CreateRelease(context.Background(), "o", "r", input) if err != nil { t.Errorf("Repositories.CreateRelease returned error: %v", err) } want := &RepositoryRelease{ID: Int64(1)} if !reflect.DeepEqual(release, want) { t.Errorf("Repositories.CreateRelease returned %+v, want %+v", release, want) } } func TestRepositoriesService_EditRelease(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &RepositoryRelease{ Name: String("n"), // Fields to be removed: ID: Int64(2), CreatedAt: &Timestamp{referenceTime}, PublishedAt: &Timestamp{referenceTime}, URL: String("http://url/"), HTMLURL: String("http://htmlurl/"), AssetsURL: String("http://assetsurl/"), Assets: []ReleaseAsset{{ID: Int64(5)}}, UploadURL: String("http://uploadurl/"), ZipballURL: String("http://zipballurl/"), TarballURL: String("http://tarballurl/"), Author: &User{Name: String("octocat")}, NodeID: String("nodeid"), } mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) { v := new(repositoryReleaseRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") want := &repositoryReleaseRequest{Name: String("n")} if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"id":1}`) }) release, _, err := client.Repositories.EditRelease(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Repositories.EditRelease returned error: %v", err) } want := &RepositoryRelease{ID: Int64(1)} if !reflect.DeepEqual(release, want) { t.Errorf("Repositories.EditRelease returned = %+v, want %+v", release, want) } } func TestRepositoriesService_DeleteRelease(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Repositories.DeleteRelease(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.DeleteRelease returned error: %v", err) } } func TestRepositoriesService_ListReleaseAssets(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases/1/assets", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} assets, _, err := client.Repositories.ListReleaseAssets(context.Background(), "o", "r", 1, opt) if err != nil { t.Errorf("Repositories.ListReleaseAssets returned error: %v", err) } want := []*ReleaseAsset{{ID: Int64(1)}} if !reflect.DeepEqual(assets, want) { t.Errorf("Repositories.ListReleaseAssets returned %+v, want %+v", assets, want) } } func TestRepositoriesService_GetReleaseAsset(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) asset, _, err := client.Repositories.GetReleaseAsset(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.GetReleaseAsset returned error: %v", err) } want := &ReleaseAsset{ID: Int64(1)} if !reflect.DeepEqual(asset, want) { t.Errorf("Repositories.GetReleaseAsset returned %+v, want %+v", asset, want) } } func TestRepositoriesService_DownloadReleaseAsset_Stream(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", defaultMediaType) w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt") fmt.Fprint(w, "Hello World") }) reader, _, err := client.Repositories.DownloadReleaseAsset(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) } want := []byte("Hello World") content, err := ioutil.ReadAll(reader) if err != nil { t.Errorf("Repositories.DownloadReleaseAsset returned bad reader: %v", err) } if !bytes.Equal(want, content) { t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", content, want) } } func TestRepositoriesService_DownloadReleaseAsset_Redirect(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", defaultMediaType) http.Redirect(w, r, "/yo", http.StatusFound) }) _, got, err := client.Repositories.DownloadReleaseAsset(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) } want := "/yo" if !strings.HasSuffix(got, want) { t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", got, want) } } func TestRepositoriesService_DownloadReleaseAsset_APIError(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", defaultMediaType) w.WriteHeader(http.StatusNotFound) fmt.Fprint(w, `{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}`) }) resp, loc, err := client.Repositories.DownloadReleaseAsset(context.Background(), "o", "r", 1) if err == nil { t.Error("Repositories.DownloadReleaseAsset did not return an error") } if resp != nil { resp.Close() t.Error("Repositories.DownloadReleaseAsset returned stream, want nil") } if loc != "" { t.Errorf(`Repositories.DownloadReleaseAsset returned "%s", want empty ""`, loc) } } func TestRepositoriesService_EditReleaseAsset(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ReleaseAsset{Name: String("n")} mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { v := new(ReleaseAsset) 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}`) }) asset, _, err := client.Repositories.EditReleaseAsset(context.Background(), "o", "r", 1, input) if err != nil { t.Errorf("Repositories.EditReleaseAsset returned error: %v", err) } want := &ReleaseAsset{ID: Int64(1)} if !reflect.DeepEqual(asset, want) { t.Errorf("Repositories.EditReleaseAsset returned = %+v, want %+v", asset, want) } } func TestRepositoriesService_DeleteReleaseAsset(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Repositories.DeleteReleaseAsset(context.Background(), "o", "r", 1) if err != nil { t.Errorf("Repositories.DeleteReleaseAsset returned error: %v", err) } } func TestRepositoriesService_UploadReleaseAsset(t *testing.T) { var ( defaultUploadOptions = &UploadOptions{Name: "n"} defaultExpectedFormValue = values{"name": "n"} mediaTypeTextPlain = "text/plain; charset=utf-8" ) uploadTests := []struct { uploadOpts *UploadOptions fileName string expectedFormValues values expectedMediaType string }{ // No file extension and no explicit media type. { defaultUploadOptions, "upload", defaultExpectedFormValue, defaultMediaType, }, // File extension and no explicit media type. { defaultUploadOptions, "upload.txt", defaultExpectedFormValue, mediaTypeTextPlain, }, // No file extension and explicit media type. { &UploadOptions{Name: "n", MediaType: "image/png"}, "upload", defaultExpectedFormValue, "image/png", }, // File extension and explicit media type. { &UploadOptions{Name: "n", MediaType: "image/png"}, "upload.png", defaultExpectedFormValue, "image/png", }, // Label provided. { &UploadOptions{Name: "n", Label: "l"}, "upload.txt", values{"name": "n", "label": "l"}, mediaTypeTextPlain, }, // No label provided. { defaultUploadOptions, "upload.txt", defaultExpectedFormValue, mediaTypeTextPlain, }, } client, mux, _, teardown := setup() defer teardown() for key, test := range uploadTests { releaseEndpoint := fmt.Sprintf("/repos/o/r/releases/%d/assets", key) mux.HandleFunc(releaseEndpoint, func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Content-Type", test.expectedMediaType) testHeader(t, r, "Content-Length", "12") testFormValues(t, r, test.expectedFormValues) testBody(t, r, "Upload me !\n") fmt.Fprintf(w, `{"id":1}`) }) file, dir, err := openTestFile(test.fileName, "Upload me !\n") if err != nil { t.Fatalf("Unable to create temp file: %v", err) } defer os.RemoveAll(dir) asset, _, err := client.Repositories.UploadReleaseAsset(context.Background(), "o", "r", int64(key), test.uploadOpts, file) if err != nil { t.Errorf("Repositories.UploadReleaseAssert returned error: %v", err) } want := &ReleaseAsset{ID: Int64(1)} if !reflect.DeepEqual(asset, want) { t.Errorf("Repositories.UploadReleaseAssert returned %+v, want %+v", asset, want) } } } go-github-28.1.1/github/repos_stats.go000066400000000000000000000174161353501270500176610ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "time" ) // ContributorStats represents a contributor to a repository and their // weekly contributions to a given repo. type ContributorStats struct { Author *Contributor `json:"author,omitempty"` Total *int `json:"total,omitempty"` Weeks []WeeklyStats `json:"weeks,omitempty"` } func (c ContributorStats) String() string { return Stringify(c) } // WeeklyStats represents the number of additions, deletions and commits // a Contributor made in a given week. type WeeklyStats struct { Week *Timestamp `json:"w,omitempty"` Additions *int `json:"a,omitempty"` Deletions *int `json:"d,omitempty"` Commits *int `json:"c,omitempty"` } func (w WeeklyStats) String() string { return Stringify(w) } // ListContributorsStats gets a repo's contributor list with additions, // deletions and commit counts. // // If this is the first time these statistics are requested for the given // repository, this method will return an *AcceptedError and a status code of // 202. This is because this is the status that GitHub returns to signify that // 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 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) if err != nil { return nil, nil, err } var contributorStats []*ContributorStats resp, err := s.client.Do(ctx, req, &contributorStats) if err != nil { return nil, resp, err } return contributorStats, resp, nil } // WeeklyCommitActivity represents the weekly commit activity for a repository. // The days array is a group of commits per day, starting on Sunday. type WeeklyCommitActivity struct { Days []int `json:"days,omitempty"` Total *int `json:"total,omitempty"` Week *Timestamp `json:"week,omitempty"` } func (w WeeklyCommitActivity) String() string { return Stringify(w) } // ListCommitActivity returns the last year of commit activity // grouped by week. The days array is a group of commits per day, // starting on Sunday. // // If this is the first time these statistics are requested for the given // repository, this method will return an *AcceptedError and a status code of // 202. This is because this is the status that GitHub returns to signify that // 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 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) if err != nil { return nil, nil, err } var weeklyCommitActivity []*WeeklyCommitActivity resp, err := s.client.Do(ctx, req, &weeklyCommitActivity) if err != nil { return nil, resp, err } return weeklyCommitActivity, resp, nil } // ListCodeFrequency returns a weekly aggregate of the number of additions and // deletions pushed to a repository. Returned WeeklyStats will contain // additions and deletions, but not total commits. // // If this is the first time these statistics are requested for the given // repository, this method will return an *AcceptedError and a status code of // 202. This is because this is the status that GitHub returns to signify that // 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 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) if err != nil { return nil, nil, err } var weeks [][]int resp, err := s.client.Do(ctx, req, &weeks) // convert int slices into WeeklyStats var stats []*WeeklyStats for _, week := range weeks { if len(week) != 3 { continue } stat := &WeeklyStats{ Week: &Timestamp{time.Unix(int64(week[0]), 0)}, Additions: Int(week[1]), Deletions: Int(week[2]), } stats = append(stats, stat) } return stats, resp, err } // RepositoryParticipation is the number of commits by everyone // who has contributed to the repository (including the owner) // as well as the number of commits by the owner themself. type RepositoryParticipation struct { All []int `json:"all,omitempty"` Owner []int `json:"owner,omitempty"` } func (r RepositoryParticipation) String() string { return Stringify(r) } // ListParticipation returns the total commit counts for the 'owner' // and total commit counts in 'all'. 'all' is everyone combined, // including the 'owner' in the last 52 weeks. If you’d like to get // the commit counts for non-owners, you can subtract 'all' from 'owner'. // // The array order is oldest week (index 0) to most recent week. // // If this is the first time these statistics are requested for the given // repository, this method will return an *AcceptedError and a status code of // 202. This is because this is the status that GitHub returns to signify that // 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 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) if err != nil { return nil, nil, err } participation := new(RepositoryParticipation) resp, err := s.client.Do(ctx, req, participation) if err != nil { return nil, resp, err } return participation, resp, nil } // PunchCard represents the number of commits made during a given hour of a // day of the week. type PunchCard struct { Day *int // Day of the week (0-6: =Sunday - Saturday). Hour *int // Hour of day (0-23). Commits *int // Number of commits. } // ListPunchCard returns the number of commits per hour in each day. // // If this is the first time these statistics are requested for the given // repository, this method will return an *AcceptedError and a status code of // 202. This is because this is the status that GitHub returns to signify that // 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 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) if err != nil { return nil, nil, err } var results [][]int resp, err := s.client.Do(ctx, req, &results) // convert int slices into Punchcards var cards []*PunchCard for _, result := range results { if len(result) != 3 { continue } card := &PunchCard{ Day: Int(result[0]), Hour: Int(result[1]), Commits: Int(result[2]), } cards = append(cards, card) } return cards, resp, err } go-github-28.1.1/github/repos_stats_test.go000066400000000000000000000136411353501270500207140ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "net/http" "reflect" "testing" "time" ) func TestRepositoriesService_ListContributorsStats(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/stats/contributors", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, ` [ { "author": { "id": 1 }, "total": 135, "weeks": [ { "w": 1367712000, "a": 6898, "d": 77, "c": 10 } ] } ] `) }) stats, _, err := client.Repositories.ListContributorsStats(context.Background(), "o", "r") if err != nil { t.Errorf("RepositoriesService.ListContributorsStats returned error: %v", err) } want := []*ContributorStats{ { Author: &Contributor{ ID: Int64(1), }, Total: Int(135), Weeks: []WeeklyStats{ { Week: &Timestamp{time.Date(2013, time.May, 05, 00, 00, 00, 0, time.UTC).Local()}, Additions: Int(6898), Deletions: Int(77), Commits: Int(10), }, }, }, } if !reflect.DeepEqual(stats, want) { t.Errorf("RepositoriesService.ListContributorsStats returned %+v, want %+v", stats, want) } } func TestRepositoriesService_ListCommitActivity(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/stats/commit_activity", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, ` [ { "days": [0, 3, 26, 20, 39, 1, 0], "total": 89, "week": 1336280400 } ] `) }) activity, _, err := client.Repositories.ListCommitActivity(context.Background(), "o", "r") if err != nil { t.Errorf("RepositoriesService.ListCommitActivity returned error: %v", err) } want := []*WeeklyCommitActivity{ { Days: []int{0, 3, 26, 20, 39, 1, 0}, Total: Int(89), Week: &Timestamp{time.Date(2012, time.May, 06, 05, 00, 00, 0, time.UTC).Local()}, }, } if !reflect.DeepEqual(activity, want) { t.Errorf("RepositoriesService.ListCommitActivity returned %+v, want %+v", activity, want) } } func TestRepositoriesService_ListCodeFrequency(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/stats/code_frequency", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[[1302998400, 1124, -435]]`) }) code, _, err := client.Repositories.ListCodeFrequency(context.Background(), "o", "r") if err != nil { t.Errorf("RepositoriesService.ListCodeFrequency returned error: %v", err) } want := []*WeeklyStats{{ Week: &Timestamp{time.Date(2011, time.April, 17, 00, 00, 00, 0, time.UTC).Local()}, Additions: Int(1124), Deletions: Int(-435), }} if !reflect.DeepEqual(code, want) { t.Errorf("RepositoriesService.ListCodeFrequency returned %+v, want %+v", code, want) } } func TestRepositoriesService_Participation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/stats/participation", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, ` { "all": [ 11,21,15,2,8,1,8,23,17,21,11,10,33, 91,38,34,22,23,32,3,43,87,71,18,13,5, 13,16,66,27,12,45,110,117,13,8,18,9,19, 26,39,12,20,31,46,91,45,10,24,9,29,7 ], "owner": [ 3,2,3,0,2,0,5,14,7,9,1,5,0, 48,19,2,0,1,10,2,23,40,35,8,8,2, 10,6,30,0,2,9,53,104,3,3,10,4,7, 11,21,4,4,22,26,63,11,2,14,1,10,3 ] } `) }) participation, _, err := client.Repositories.ListParticipation(context.Background(), "o", "r") if err != nil { t.Errorf("RepositoriesService.ListParticipation returned error: %v", err) } want := &RepositoryParticipation{ All: []int{ 11, 21, 15, 2, 8, 1, 8, 23, 17, 21, 11, 10, 33, 91, 38, 34, 22, 23, 32, 3, 43, 87, 71, 18, 13, 5, 13, 16, 66, 27, 12, 45, 110, 117, 13, 8, 18, 9, 19, 26, 39, 12, 20, 31, 46, 91, 45, 10, 24, 9, 29, 7, }, Owner: []int{ 3, 2, 3, 0, 2, 0, 5, 14, 7, 9, 1, 5, 0, 48, 19, 2, 0, 1, 10, 2, 23, 40, 35, 8, 8, 2, 10, 6, 30, 0, 2, 9, 53, 104, 3, 3, 10, 4, 7, 11, 21, 4, 4, 22, 26, 63, 11, 2, 14, 1, 10, 3, }, } if !reflect.DeepEqual(participation, want) { t.Errorf("RepositoriesService.ListParticipation returned %+v, want %+v", participation, want) } } func TestRepositoriesService_ListPunchCard(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/stats/punch_card", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[ [0, 0, 5], [0, 1, 43], [0, 2, 21] ]`) }) card, _, err := client.Repositories.ListPunchCard(context.Background(), "o", "r") if err != nil { t.Errorf("RepositoriesService.ListPunchCard returned error: %v", err) } want := []*PunchCard{ {Day: Int(0), Hour: Int(0), Commits: Int(5)}, {Day: Int(0), Hour: Int(1), Commits: Int(43)}, {Day: Int(0), Hour: Int(2), Commits: Int(21)}, } if !reflect.DeepEqual(card, want) { t.Errorf("RepositoriesService.ListPunchCard returned %+v, want %+v", card, want) } } func TestRepositoriesService_AcceptedError(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/stats/contributors", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") // This response indicates the fork will happen asynchronously. w.WriteHeader(http.StatusAccepted) fmt.Fprint(w, `{"id":1}`) }) stats, _, err := client.Repositories.ListContributorsStats(context.Background(), "o", "r") if err == nil { t.Errorf("RepositoriesService.AcceptedError should have returned an error") } if _, ok := err.(*AcceptedError); !ok { t.Errorf("RepositoriesService.AcceptedError returned an AcceptedError: %v", err) } if stats != nil { t.Errorf("RepositoriesService.AcceptedError expected stats to be nil: %v", stats) } } go-github-28.1.1/github/repos_statuses.go000066400000000000000000000101701353501270500203640ustar00rootroot00000000000000// 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" "net/url" "time" ) // RepoStatus represents the status of a repository at a particular reference. type RepoStatus struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` URL *string `json:"url,omitempty"` // State is the current state of the repository. Possible values are: // pending, success, error, or failure. State *string `json:"state,omitempty"` // TargetURL is the URL of the page representing this status. It will be // linked from the GitHub UI to allow users to see the source of the status. TargetURL *string `json:"target_url,omitempty"` // Description is a short high level summary of the status. Description *string `json:"description,omitempty"` // A string label to differentiate this status from the statuses of other systems. Context *string `json:"context,omitempty"` Creator *User `json:"creator,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` } func (r RepoStatus) String() string { return Stringify(r) } // ListStatuses lists the statuses of a repository at the specified // reference. ref can be a SHA, a branch name, or a tag name. // // GitHub API docs: https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref string, opt *ListOptions) ([]*RepoStatus, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/statuses", owner, repo, url.QueryEscape(ref)) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var statuses []*RepoStatus resp, err := s.client.Do(ctx, req, &statuses) if err != nil { return nil, resp, err } return statuses, resp, nil } // CreateStatus creates a new status for a repository at the specified // reference. Ref can be a SHA, a branch name, or a tag name. // // GitHub API docs: https://developer.github.com/v3/repos/statuses/#create-a-status func (s *RepositoriesService) CreateStatus(ctx context.Context, owner, repo, ref string, status *RepoStatus) (*RepoStatus, *Response, error) { u := fmt.Sprintf("repos/%v/%v/statuses/%v", owner, repo, url.QueryEscape(ref)) req, err := s.client.NewRequest("POST", u, status) if err != nil { return nil, nil, err } repoStatus := new(RepoStatus) resp, err := s.client.Do(ctx, req, repoStatus) if err != nil { return nil, resp, err } return repoStatus, resp, nil } // CombinedStatus represents the combined status of a repository at a particular reference. type CombinedStatus struct { // State is the combined state of the repository. Possible values are: // failure, pending, or success. State *string `json:"state,omitempty"` Name *string `json:"name,omitempty"` SHA *string `json:"sha,omitempty"` TotalCount *int `json:"total_count,omitempty"` Statuses []RepoStatus `json:"statuses,omitempty"` CommitURL *string `json:"commit_url,omitempty"` RepositoryURL *string `json:"repository_url,omitempty"` } func (s CombinedStatus) String() string { return Stringify(s) } // GetCombinedStatus returns the combined status of a repository at the specified // reference. ref can be a SHA, a branch name, or a tag name. // // GitHub API docs: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref func (s *RepositoriesService) GetCombinedStatus(ctx context.Context, owner, repo, ref string, opt *ListOptions) (*CombinedStatus, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/status", owner, repo, url.QueryEscape(ref)) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } status := new(CombinedStatus) resp, err := s.client.Do(ctx, req, status) if err != nil { return nil, resp, err } return status, resp, nil } go-github-28.1.1/github/repos_statuses_test.go000066400000000000000000000060071353501270500214270ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestRepositoriesService_ListStatuses(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/commits/r/statuses", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} statuses, _, err := client.Repositories.ListStatuses(context.Background(), "o", "r", "r", opt) if err != nil { t.Errorf("Repositories.ListStatuses returned error: %v", err) } want := []*RepoStatus{{ID: Int64(1)}} if !reflect.DeepEqual(statuses, want) { t.Errorf("Repositories.ListStatuses returned %+v, want %+v", statuses, want) } } func TestRepositoriesService_ListStatuses_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.ListStatuses(context.Background(), "%", "r", "r", nil) testURLParseError(t, err) } func TestRepositoriesService_CreateStatus(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &RepoStatus{State: String("s"), TargetURL: String("t"), Description: String("d")} mux.HandleFunc("/repos/o/r/statuses/r", func(w http.ResponseWriter, r *http.Request) { v := new(RepoStatus) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) status, _, err := client.Repositories.CreateStatus(context.Background(), "o", "r", "r", input) if err != nil { t.Errorf("Repositories.CreateStatus returned error: %v", err) } want := &RepoStatus{ID: Int64(1)} if !reflect.DeepEqual(status, want) { t.Errorf("Repositories.CreateStatus returned %+v, want %+v", status, want) } } func TestRepositoriesService_CreateStatus_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.CreateStatus(context.Background(), "%", "r", "r", nil) testURLParseError(t, err) } func TestRepositoriesService_GetCombinedStatus(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/commits/r/status", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `{"state":"success", "statuses":[{"id":1}]}`) }) opt := &ListOptions{Page: 2} status, _, err := client.Repositories.GetCombinedStatus(context.Background(), "o", "r", "r", opt) if err != nil { t.Errorf("Repositories.GetCombinedStatus returned error: %v", err) } want := &CombinedStatus{State: String("success"), Statuses: []RepoStatus{{ID: Int64(1)}}} if !reflect.DeepEqual(status, want) { t.Errorf("Repositories.GetCombinedStatus returned %+v, want %+v", status, want) } } go-github-28.1.1/github/repos_test.go000066400000000000000000001456721353501270500175100ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "strings" "testing" "time" ) func TestRepositoriesService_List_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeTopicsPreview} mux.HandleFunc("/user/repos", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `[{"id":1},{"id":2}]`) }) ctx := context.Background() got, _, err := client.Repositories.List(ctx, "", nil) if err != nil { t.Errorf("Repositories.List returned error: %v", err) } want := []*Repository{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.List returned %+v, want %+v", got, want) } // Test addOptions failure _, _, err = client.Repositories.List(ctx, "\n", &RepositoryListOptions{}) if err == nil { t.Error("bad options List err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err := client.Repositories.List(ctx, "", nil) if got != nil { t.Errorf("rate.Reset.Time > now List = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now List resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now List err = nil, want error") } } func TestRepositoriesService_List_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeTopicsPreview} mux.HandleFunc("/users/u/repos", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{ "visibility": "public", "affiliation": "owner,collaborator", "sort": "created", "direction": "asc", "page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) opt := &RepositoryListOptions{ Visibility: "public", Affiliation: "owner,collaborator", Sort: "created", Direction: "asc", ListOptions: ListOptions{Page: 2}, } repos, _, err := client.Repositories.List(context.Background(), "u", opt) if err != nil { t.Errorf("Repositories.List returned error: %v", err) } want := []*Repository{{ID: Int64(1)}} if !reflect.DeepEqual(repos, want) { t.Errorf("Repositories.List returned %+v, want %+v", repos, want) } } func TestRepositoriesService_List_specifiedUser_type(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeTopicsPreview} mux.HandleFunc("/users/u/repos", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{ "type": "owner", }) fmt.Fprint(w, `[{"id":1}]`) }) opt := &RepositoryListOptions{ Type: "owner", } repos, _, err := client.Repositories.List(context.Background(), "u", opt) if err != nil { t.Errorf("Repositories.List returned error: %v", err) } want := []*Repository{{ID: Int64(1)}} if !reflect.DeepEqual(repos, want) { t.Errorf("Repositories.List returned %+v, want %+v", repos, want) } } func TestRepositoriesService_List_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.List(context.Background(), "%", nil) testURLParseError(t, err) } func TestRepositoriesService_ListByOrg(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeTopicsPreview} mux.HandleFunc("/orgs/o/repos", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{ "type": "forks", "page": "2", }) fmt.Fprint(w, `[{"id":1}]`) }) ctx := context.Background() opt := &RepositoryListByOrgOptions{"forks", ListOptions{Page: 2}} got, _, err := client.Repositories.ListByOrg(ctx, "o", opt) if err != nil { t.Errorf("Repositories.ListByOrg returned error: %v", err) } want := []*Repository{{ID: Int64(1)}} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ListByOrg returned %+v, want %+v", got, want) } // Test addOptions failure _, _, err = client.Repositories.ListByOrg(ctx, "\n", opt) if err == nil { t.Error("bad options ListByOrg err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err := client.Repositories.ListByOrg(ctx, "o", opt) if got != nil { t.Errorf("rate.Reset.Time > now ListByOrg = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now ListByOrg resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now ListByOrg err = nil, want error") } } func TestRepositoriesService_ListByOrg_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.ListByOrg(context.Background(), "%", nil) testURLParseError(t, err) } func TestRepositoriesService_ListAll(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repositories", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "since": "1", }) fmt.Fprint(w, `[{"id":1}]`) }) ctx := context.Background() opt := &RepositoryListAllOptions{1} got, _, err := client.Repositories.ListAll(ctx, opt) if err != nil { t.Errorf("Repositories.ListAll returned error: %v", err) } want := []*Repository{{ID: Int64(1)}} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ListAll returned %+v, want %+v", got, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Repositories.ListAll(ctx, &RepositoryListAllOptions{1}) if got != nil { t.Errorf("client.BaseURL.Path='' ListAll = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' ListAll resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' ListAll err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Repositories.ListAll(ctx, &RepositoryListAllOptions{1}) if got != nil { t.Errorf("rate.Reset.Time > now ListAll = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now ListAll resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now ListAll err = nil, want error") } } func TestRepositoriesService_Create_user(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Repository{ Name: String("n"), Archived: Bool(true), // not passed along. } mux.HandleFunc("/user/repos", func(w http.ResponseWriter, r *http.Request) { v := new(createRepoRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeRepositoryTemplatePreview) want := &createRepoRequest{Name: String("n")} if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"id":1}`) }) ctx := context.Background() got, _, err := client.Repositories.Create(ctx, "", input) if err != nil { t.Errorf("Repositories.Create returned error: %v", err) } want := &Repository{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.Create returned %+v, want %+v", got, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Repositories.Create(ctx, "", input) if got != nil { t.Errorf("client.BaseURL.Path='' Create = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' Create resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' Create err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Repositories.Create(ctx, "", input) if got != nil { t.Errorf("rate.Reset.Time > now Create = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now Create resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now Create err = nil, want error") } } func TestRepositoriesService_Create_org(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Repository{ Name: String("n"), Archived: Bool(true), // not passed along. } mux.HandleFunc("/orgs/o/repos", func(w http.ResponseWriter, r *http.Request) { v := new(createRepoRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeRepositoryTemplatePreview) want := &createRepoRequest{Name: String("n")} if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"id":1}`) }) repo, _, err := client.Repositories.Create(context.Background(), "o", input) if err != nil { t.Errorf("Repositories.Create returned error: %v", err) } want := &Repository{ID: Int64(1)} if !reflect.DeepEqual(repo, want) { t.Errorf("Repositories.Create returned %+v, want %+v", repo, want) } } func TestRepositoriesService_CreateFromTemplate(t *testing.T) { client, mux, _, teardown := setup() defer teardown() templateRepoReq := &TemplateRepoRequest{ Name: String("n"), } mux.HandleFunc("/repos/to/tr/generate", func(w http.ResponseWriter, r *http.Request) { v := new(TemplateRepoRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeRepositoryTemplatePreview) want := &TemplateRepoRequest{Name: String("n")} if !reflect.DeepEqual(v, want) { t.Errorf("Request body = %+v, want %+v", v, want) } fmt.Fprint(w, `{"id":1,"name":"n"}`) }) ctx := context.Background() got, _, err := client.Repositories.CreateFromTemplate(ctx, "to", "tr", templateRepoReq) if err != nil { t.Errorf("Repositories.CreateFromTemplate returned error: %v", err) } want := &Repository{ID: Int64(1), Name: String("n")} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.CreateFromTemplate returned %+v, want %+v", got, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Repositories.CreateFromTemplate(ctx, "to", "tr", templateRepoReq) if got != nil { t.Errorf("client.BaseURL.Path='' CreateFromTemplate = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' CreateFromTemplate resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' CreateFromTemplate err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Repositories.CreateFromTemplate(ctx, "to", "tr", templateRepoReq) if got != nil { t.Errorf("rate.Reset.Time > now CreateFromTemplate = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now CreateFromTemplate resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now CreateFromTemplate err = nil, want error") } } func TestRepositoriesService_Get(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview, mediaTypeRepositoryTemplatePreview} mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`) }) ctx := context.Background() got, _, err := client.Repositories.Get(ctx, "o", "r") if err != nil { t.Errorf("Repositories.Get returned error: %v", err) } want := &Repository{ID: Int64(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}, License: &License{Key: String("mit")}} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.Get returned %+v, want %+v", got, want) } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err := client.Repositories.Get(ctx, "o", "r") if got != nil { t.Errorf("rate.Reset.Time > now Get = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now Get resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now Get err = nil, want error") } } func TestRepositoriesService_GetCodeOfConduct(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/community/code_of_conduct", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeCodesOfConductPreview) fmt.Fprint(w, `{ "key": "key", "name": "name", "url": "url", "body": "body"}`, ) }) ctx := context.Background() got, _, err := client.Repositories.GetCodeOfConduct(ctx, "o", "r") if err != nil { t.Errorf("Repositories.GetCodeOfConduct returned error: %v", err) } want := &CodeOfConduct{ Key: String("key"), Name: String("name"), URL: String("url"), Body: String("body"), } if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.GetCodeOfConduct returned %+v, want %+v", got, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Repositories.GetCodeOfConduct(ctx, "o", "r") if got != nil { t.Errorf("client.BaseURL.Path='' GetCodeOfConduct = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' GetCodeOfConduct resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' GetCodeOfConduct err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Repositories.GetCodeOfConduct(ctx, "o", "r") if got != nil { t.Errorf("rate.Reset.Time > now GetCodeOfConduct = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now GetCodeOfConduct resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now GetCodeOfConduct err = nil, want error") } } func TestRepositoriesService_GetByID(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repositories/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`) }) ctx := context.Background() got, _, err := client.Repositories.GetByID(ctx, 1) if err != nil { t.Fatalf("Repositories.GetByID returned error: %v", err) } want := &Repository{ID: Int64(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}, License: &License{Key: String("mit")}} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.GetByID returned %+v, want %+v", got, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Repositories.GetByID(ctx, 1) if got != nil { t.Errorf("client.BaseURL.Path='' GetByID = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' GetByID resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' GetByID err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Repositories.GetByID(ctx, 1) if got != nil { t.Errorf("rate.Reset.Time > now GetByID = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now GetByID resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now GetByID err = nil, want error") } } func TestRepositoriesService_Edit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() i := true input := &Repository{HasIssues: &i} mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) { v := new(Repository) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeRepositoryTemplatePreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) ctx := context.Background() got, _, err := client.Repositories.Edit(ctx, "o", "r", input) if err != nil { t.Errorf("Repositories.Edit returned error: %v", err) } want := &Repository{ID: Int64(1)} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.Edit returned %+v, want %+v", got, want) } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err := client.Repositories.Edit(ctx, "o", "r", input) if got != nil { t.Errorf("rate.Reset.Time > now Edit = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now Edit resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now Edit err = nil, want error") } } func TestRepositoriesService_Delete(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) ctx := context.Background() _, err := client.Repositories.Delete(ctx, "o", "r") if err != nil { t.Errorf("Repositories.Delete returned error: %v", err) } // Test s.client.NewRequest failure client.BaseURL.Path = "" resp, err := client.Repositories.Delete(ctx, "o", "r") if resp != nil { t.Errorf("client.BaseURL.Path='' Delete resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' Delete err = nil, want error") } } func TestRepositoriesService_Get_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.Get(context.Background(), "%", "r") testURLParseError(t, err) } func TestRepositoriesService_Edit_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.Edit(context.Background(), "%", "r", nil) testURLParseError(t, err) } func TestRepositoriesService_EnableVulnerabilityAlerts(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/vulnerability-alerts", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeRequiredVulnerabilityAlertsPreview) w.WriteHeader(http.StatusNoContent) }) if _, err := client.Repositories.EnableVulnerabilityAlerts(context.Background(), "o", "r"); err != nil { t.Errorf("Repositories.EnableVulnerabilityAlerts returned error: %v", err) } } func TestRepositoriesService_DisableVulnerabilityAlerts(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/vulnerability-alerts", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeRequiredVulnerabilityAlertsPreview) w.WriteHeader(http.StatusNoContent) }) if _, err := client.Repositories.DisableVulnerabilityAlerts(context.Background(), "o", "r"); err != nil { t.Errorf("Repositories.DisableVulnerabilityAlerts returned error: %v", err) } } func TestRepositoriesService_EnableAutomatedSecurityFixes(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/automated-security-fixes", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeRequiredAutomatedSecurityFixesPreview) w.WriteHeader(http.StatusNoContent) }) if _, err := client.Repositories.EnableAutomatedSecurityFixes(context.Background(), "o", "r"); err != nil { t.Errorf("Repositories.EnableAutomatedSecurityFixes returned error: %v", err) } } func TestRepositoriesService_DisableAutomatedSecurityFixes(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/automated-security-fixes", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeRequiredAutomatedSecurityFixesPreview) w.WriteHeader(http.StatusNoContent) }) if _, err := client.Repositories.DisableAutomatedSecurityFixes(context.Background(), "o", "r"); err != nil { t.Errorf("Repositories.DisableAutomatedSecurityFixes returned error: %v", err) } } func TestRepositoriesService_ListContributors(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/contributors", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "anon": "true", "page": "2", }) fmt.Fprint(w, `[{"contributions":42}]`) }) opts := &ListContributorsOptions{Anon: "true", ListOptions: ListOptions{Page: 2}} contributors, _, err := client.Repositories.ListContributors(context.Background(), "o", "r", opts) if err != nil { t.Errorf("Repositories.ListContributors returned error: %v", err) } want := []*Contributor{{Contributions: Int(42)}} if !reflect.DeepEqual(contributors, want) { t.Errorf("Repositories.ListContributors returned %+v, want %+v", contributors, want) } } func TestRepositoriesService_ListLanguages(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/languages", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"go":1}`) }) languages, _, err := client.Repositories.ListLanguages(context.Background(), "o", "r") if err != nil { t.Errorf("Repositories.ListLanguages returned error: %v", err) } want := map[string]int{"go": 1} if !reflect.DeepEqual(languages, want) { t.Errorf("Repositories.ListLanguages returned %+v, want %+v", languages, want) } } func TestRepositoriesService_ListTeams(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/teams", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} teams, _, err := client.Repositories.ListTeams(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListTeams returned error: %v", err) } want := []*Team{{ID: Int64(1)}} if !reflect.DeepEqual(teams, want) { t.Errorf("Repositories.ListTeams returned %+v, want %+v", teams, want) } } func TestRepositoriesService_ListTags(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/tags", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"name":"n", "commit" : {"sha" : "s", "url" : "u"}, "zipball_url": "z", "tarball_url": "t"}]`) }) opt := &ListOptions{Page: 2} tags, _, err := client.Repositories.ListTags(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListTags returned error: %v", err) } want := []*RepositoryTag{ { Name: String("n"), Commit: &Commit{ SHA: String("s"), URL: String("u"), }, ZipballURL: String("z"), TarballURL: String("t"), }, } if !reflect.DeepEqual(tags, want) { t.Errorf("Repositories.ListTags returned %+v, want %+v", tags, want) } } func TestRepositoriesService_ListBranches(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") // TODO: remove custom Accept header when this API fully launches testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"name":"master", "commit" : {"sha" : "a57781", "url" : "https://api.github.com/repos/o/r/commits/a57781"}}]`) }) opt := &ListOptions{Page: 2} branches, _, err := client.Repositories.ListBranches(context.Background(), "o", "r", opt) if err != nil { t.Errorf("Repositories.ListBranches returned error: %v", err) } want := []*Branch{{Name: String("master"), Commit: &RepositoryCommit{SHA: String("a57781"), URL: String("https://api.github.com/repos/o/r/commits/a57781")}}} if !reflect.DeepEqual(branches, want) { t.Errorf("Repositories.ListBranches returned %+v, want %+v", branches, want) } } func TestRepositoriesService_GetBranch(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") // TODO: remove custom Accept header when this API fully launches testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true}`) }) branch, _, err := client.Repositories.GetBranch(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.GetBranch returned error: %v", err) } want := &Branch{ Name: String("n"), Commit: &RepositoryCommit{ SHA: String("s"), Commit: &Commit{ Message: String("m"), }, }, Protected: Bool(true), } if !reflect.DeepEqual(branch, want) { t.Errorf("Repositories.GetBranch returned %+v, want %+v", branch, want) } } func TestRepositoriesService_GetBranchProtection(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) { v := new(ProtectionRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "GET") // TODO: remove custom Accept header when this API fully launches testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) fmt.Fprintf(w, `{ "required_status_checks":{ "strict":true, "contexts":["continuous-integration"] }, "required_pull_request_reviews":{ "dismissal_restrictions":{ "users":[{ "id":3, "login":"u" }], "teams":[{ "id":4, "slug":"t" }] }, "dismiss_stale_reviews":true, "require_code_owner_reviews":true, "required_approving_review_count":1 }, "enforce_admins":{ "url":"/repos/o/r/branches/b/protection/enforce_admins", "enabled":true }, "restrictions":{ "users":[{"id":1,"login":"u"}], "teams":[{"id":2,"slug":"t"}] } }`) }) protection, _, err := client.Repositories.GetBranchProtection(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.GetBranchProtection returned error: %v", err) } want := &Protection{ RequiredStatusChecks: &RequiredStatusChecks{ Strict: true, Contexts: []string{"continuous-integration"}, }, RequiredPullRequestReviews: &PullRequestReviewsEnforcement{ DismissStaleReviews: true, DismissalRestrictions: DismissalRestrictions{ Users: []*User{ {Login: String("u"), ID: Int64(3)}, }, Teams: []*Team{ {Slug: String("t"), ID: Int64(4)}, }, }, RequireCodeOwnerReviews: true, RequiredApprovingReviewCount: 1, }, EnforceAdmins: &AdminEnforcement{ URL: String("/repos/o/r/branches/b/protection/enforce_admins"), Enabled: true, }, Restrictions: &BranchRestrictions{ Users: []*User{ {Login: String("u"), ID: Int64(1)}, }, Teams: []*Team{ {Slug: String("t"), ID: Int64(2)}, }, }, } if !reflect.DeepEqual(protection, want) { t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want) } } func TestRepositoriesService_UpdateBranchProtection(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &ProtectionRequest{ RequiredStatusChecks: &RequiredStatusChecks{ Strict: true, Contexts: []string{"continuous-integration"}, }, RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{ DismissStaleReviews: true, DismissalRestrictionsRequest: &DismissalRestrictionsRequest{ Users: &[]string{"uu"}, Teams: &[]string{"tt"}, }, }, Restrictions: &BranchRestrictionsRequest{ Users: []string{"u"}, Teams: []string{"t"}, }, } mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) { v := new(ProtectionRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } // TODO: remove custom Accept header when this API fully launches testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) fmt.Fprintf(w, `{ "required_status_checks":{ "strict":true, "contexts":["continuous-integration"] }, "required_pull_request_reviews":{ "dismissal_restrictions":{ "users":[{ "id":3, "login":"uu" }], "teams":[{ "id":4, "slug":"tt" }] }, "dismiss_stale_reviews":true, "require_code_owner_reviews":true }, "restrictions":{ "users":[{"id":1,"login":"u"}], "teams":[{"id":2,"slug":"t"}] } }`) }) protection, _, err := client.Repositories.UpdateBranchProtection(context.Background(), "o", "r", "b", input) if err != nil { t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err) } want := &Protection{ RequiredStatusChecks: &RequiredStatusChecks{ Strict: true, Contexts: []string{"continuous-integration"}, }, RequiredPullRequestReviews: &PullRequestReviewsEnforcement{ DismissStaleReviews: true, DismissalRestrictions: DismissalRestrictions{ Users: []*User{ {Login: String("uu"), ID: Int64(3)}, }, Teams: []*Team{ {Slug: String("tt"), ID: Int64(4)}, }, }, RequireCodeOwnerReviews: true, }, Restrictions: &BranchRestrictions{ Users: []*User{ {Login: String("u"), ID: Int64(1)}, }, Teams: []*Team{ {Slug: String("t"), ID: Int64(2)}, }, }, } if !reflect.DeepEqual(protection, want) { t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want) } } func TestRepositoriesService_RemoveBranchProtection(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") // TODO: remove custom Accept header when this API fully launches testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Repositories.RemoveBranchProtection(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.RemoveBranchProtection returned error: %v", err) } } func TestRepositoriesService_ListLanguages_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Repositories.ListLanguages(context.Background(), "%", "%") testURLParseError(t, err) } func TestRepositoriesService_License(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/license", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"name": "LICENSE", "path": "LICENSE", "license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","featured":true}}`) }) got, _, err := client.Repositories.License(context.Background(), "o", "r") if err != nil { t.Errorf("Repositories.License returned error: %v", err) } want := &RepositoryLicense{ Name: String("LICENSE"), Path: String("LICENSE"), License: &License{ Name: String("MIT License"), Key: String("mit"), SPDXID: String("MIT"), URL: String("https://api.github.com/licenses/mit"), Featured: Bool(true), }, } if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.License returned %+v, want %+v", got, want) } } func TestRepositoriesService_GetRequiredStatusChecks(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) { v := new(ProtectionRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "GET") // TODO: remove custom Accept header when this API fully launches testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) fmt.Fprint(w, `{"strict": true,"contexts": ["x","y","z"]}`) }) checks, _, err := client.Repositories.GetRequiredStatusChecks(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.GetRequiredStatusChecks returned error: %v", err) } want := &RequiredStatusChecks{ Strict: true, Contexts: []string{"x", "y", "z"}, } if !reflect.DeepEqual(checks, want) { t.Errorf("Repositories.GetRequiredStatusChecks returned %+v, want %+v", checks, want) } } func TestRepositoriesService_UpdateRequiredStatusChecks(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &RequiredStatusChecksRequest{ Strict: Bool(true), Contexts: []string{"continuous-integration"}, } mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) { v := new(RequiredStatusChecksRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } testHeader(t, r, "Accept", mediaTypeV3) fmt.Fprintf(w, `{"strict":true,"contexts":["continuous-integration"]}`) }) statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(context.Background(), "o", "r", "b", input) if err != nil { t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err) } want := &RequiredStatusChecks{ Strict: true, Contexts: []string{"continuous-integration"}, } if !reflect.DeepEqual(statusChecks, want) { t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want) } } func TestRepositoriesService_ListRequiredStatusChecksContexts(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks/contexts", func(w http.ResponseWriter, r *http.Request) { v := new(ProtectionRequest) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "GET") // TODO: remove custom Accept header when this API fully launches testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) fmt.Fprint(w, `["x", "y", "z"]`) }) contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.ListRequiredStatusChecksContexts returned error: %v", err) } want := []string{"x", "y", "z"} if !reflect.DeepEqual(contexts, want) { t.Errorf("Repositories.ListRequiredStatusChecksContexts returned %+v, want %+v", contexts, want) } } func TestRepositoriesService_GetPullRequestReviewEnforcement(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") // TODO: remove custom Accept header when this API fully launches testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) fmt.Fprintf(w, `{ "dismissal_restrictions":{ "users":[{"id":1,"login":"u"}], "teams":[{"id":2,"slug":"t"}] }, "dismiss_stale_reviews":true, "require_code_owner_reviews":true, "required_approving_review_count":1 }`) }) enforcement, _, err := client.Repositories.GetPullRequestReviewEnforcement(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.GetPullRequestReviewEnforcement returned error: %v", err) } want := &PullRequestReviewsEnforcement{ DismissStaleReviews: true, DismissalRestrictions: DismissalRestrictions{ Users: []*User{ {Login: String("u"), ID: Int64(1)}, }, Teams: []*Team{ {Slug: String("t"), ID: Int64(2)}, }, }, RequireCodeOwnerReviews: true, RequiredApprovingReviewCount: 1, } if !reflect.DeepEqual(enforcement, want) { t.Errorf("Repositories.GetPullRequestReviewEnforcement returned %+v, want %+v", enforcement, want) } } func TestRepositoriesService_UpdatePullRequestReviewEnforcement(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &PullRequestReviewsEnforcementUpdate{ DismissalRestrictionsRequest: &DismissalRestrictionsRequest{ Users: &[]string{"u"}, Teams: &[]string{"t"}, }, } mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) { v := new(PullRequestReviewsEnforcementUpdate) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } // TODO: remove custom Accept header when this API fully launches testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) fmt.Fprintf(w, `{ "dismissal_restrictions":{ "users":[{"id":1,"login":"u"}], "teams":[{"id":2,"slug":"t"}] }, "dismiss_stale_reviews":true, "require_code_owner_reviews":true, "required_approving_review_count":3 }`) }) enforcement, _, err := client.Repositories.UpdatePullRequestReviewEnforcement(context.Background(), "o", "r", "b", input) if err != nil { t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned error: %v", err) } want := &PullRequestReviewsEnforcement{ DismissStaleReviews: true, DismissalRestrictions: DismissalRestrictions{ Users: []*User{ {Login: String("u"), ID: Int64(1)}, }, Teams: []*Team{ {Slug: String("t"), ID: Int64(2)}, }, }, RequireCodeOwnerReviews: true, RequiredApprovingReviewCount: 3, } if !reflect.DeepEqual(enforcement, want) { t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned %+v, want %+v", enforcement, want) } } func TestRepositoriesService_DisableDismissalRestrictions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") // TODO: remove custom Accept header when this API fully launches testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) testBody(t, r, `{"dismissal_restrictions":[]}`+"\n") fmt.Fprintf(w, `{"dismissal_restrictions":{"users":[],"teams":[]},"dismiss_stale_reviews":true,"require_code_owner_reviews":true,"required_approving_review_count":1}`) }) enforcement, _, err := client.Repositories.DisableDismissalRestrictions(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.DisableDismissalRestrictions returned error: %v", err) } want := &PullRequestReviewsEnforcement{ DismissStaleReviews: true, DismissalRestrictions: DismissalRestrictions{ Users: []*User{}, Teams: []*Team{}, }, RequireCodeOwnerReviews: true, RequiredApprovingReviewCount: 1, } if !reflect.DeepEqual(enforcement, want) { t.Errorf("Repositories.DisableDismissalRestrictions returned %+v, want %+v", enforcement, want) } } func TestRepositoriesService_RemovePullRequestReviewEnforcement(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Repositories.RemovePullRequestReviewEnforcement(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.RemovePullRequestReviewEnforcement returned error: %v", err) } } func TestRepositoriesService_GetAdminEnforcement(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`) }) enforcement, _, err := client.Repositories.GetAdminEnforcement(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.GetAdminEnforcement returned error: %v", err) } want := &AdminEnforcement{ URL: String("/repos/o/r/branches/b/protection/enforce_admins"), Enabled: true, } if !reflect.DeepEqual(enforcement, want) { t.Errorf("Repositories.GetAdminEnforcement returned %+v, want %+v", enforcement, want) } } func TestRepositoriesService_AddAdminEnforcement(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`) }) enforcement, _, err := client.Repositories.AddAdminEnforcement(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.AddAdminEnforcement returned error: %v", err) } want := &AdminEnforcement{ URL: String("/repos/o/r/branches/b/protection/enforce_admins"), Enabled: true, } if !reflect.DeepEqual(enforcement, want) { t.Errorf("Repositories.AddAdminEnforcement returned %+v, want %+v", enforcement, want) } } func TestRepositoriesService_RemoveAdminEnforcement(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Repositories.RemoveAdminEnforcement(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.RemoveAdminEnforcement returned error: %v", err) } } func TestRepositoriesService_GetSignaturesProtectedBranch(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeSignaturePreview) fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":false}`) }) signature, _, err := client.Repositories.GetSignaturesProtectedBranch(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.GetSignaturesProtectedBranch returned error: %v", err) } want := &SignaturesProtectedBranch{ URL: String("/repos/o/r/branches/b/protection/required_signatures"), Enabled: Bool(false), } if !reflect.DeepEqual(signature, want) { t.Errorf("Repositories.GetSignaturesProtectedBranch returned %+v, want %+v", signature, want) } } func TestRepositoriesService_RequireSignaturesOnProtectedBranch(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeSignaturePreview) fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":true}`) }) signature, _, err := client.Repositories.RequireSignaturesOnProtectedBranch(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned error: %v", err) } want := &SignaturesProtectedBranch{ URL: String("/repos/o/r/branches/b/protection/required_signatures"), Enabled: Bool(true), } if !reflect.DeepEqual(signature, want) { t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned %+v, want %+v", signature, want) } } func TestRepositoriesService_OptionalSignaturesOnProtectedBranch(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeSignaturePreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Repositories.OptionalSignaturesOnProtectedBranch(context.Background(), "o", "r", "b") if err != nil { t.Errorf("Repositories.OptionalSignaturesOnProtectedBranch returned error: %v", err) } } func TestPullRequestReviewsEnforcementRequest_MarshalJSON_nilDismissalRestirctions(t *testing.T) { req := PullRequestReviewsEnforcementRequest{} got, err := json.Marshal(req) if err != nil { t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err) } want := `{"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}` if want != string(got) { t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want) } req = PullRequestReviewsEnforcementRequest{ DismissalRestrictionsRequest: &DismissalRestrictionsRequest{}, } got, err = json.Marshal(req) if err != nil { t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err) } want = `{"dismissal_restrictions":{},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}` if want != string(got) { t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want) } req = PullRequestReviewsEnforcementRequest{ DismissalRestrictionsRequest: &DismissalRestrictionsRequest{ Users: &[]string{}, Teams: &[]string{}, }, } got, err = json.Marshal(req) if err != nil { t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err) } want = `{"dismissal_restrictions":{"users":[],"teams":[]},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}` if want != string(got) { t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want) } } func TestRepositoriesService_ListAllTopics(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeTopicsPreview) fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`) }) got, _, err := client.Repositories.ListAllTopics(context.Background(), "o", "r") if err != nil { t.Fatalf("Repositories.ListAllTopics returned error: %v", err) } want := []string{"go", "go-github", "github"} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want) } } func TestRepositoriesService_ListAllTopics_emptyTopics(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeTopicsPreview) fmt.Fprint(w, `{"names":[]}`) }) got, _, err := client.Repositories.ListAllTopics(context.Background(), "o", "r") if err != nil { t.Fatalf("Repositories.ListAllTopics returned error: %v", err) } want := []string{} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want) } } func TestRepositoriesService_ReplaceAllTopics(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeTopicsPreview) fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`) }) got, _, err := client.Repositories.ReplaceAllTopics(context.Background(), "o", "r", []string{"go", "go-github", "github"}) if err != nil { t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err) } want := []string{"go", "go-github", "github"} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want) } } func TestRepositoriesService_ReplaceAllTopics_nilSlice(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeTopicsPreview) testBody(t, r, `{"names":[]}`+"\n") fmt.Fprint(w, `{"names":[]}`) }) got, _, err := client.Repositories.ReplaceAllTopics(context.Background(), "o", "r", nil) if err != nil { t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err) } want := []string{} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want) } } func TestRepositoriesService_ReplaceAllTopics_emptySlice(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeTopicsPreview) testBody(t, r, `{"names":[]}`+"\n") fmt.Fprint(w, `{"names":[]}`) }) got, _, err := client.Repositories.ReplaceAllTopics(context.Background(), "o", "r", []string{}) if err != nil { t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err) } want := []string{} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want) } } func TestRepositoriesService_Transfer(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := TransferRequest{NewOwner: "a", TeamID: []int64{123}} mux.HandleFunc("/repos/o/r/transfer", func(w http.ResponseWriter, r *http.Request) { var v TransferRequest json.NewDecoder(r.Body).Decode(&v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeRepositoryTransferPreview) if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"owner":{"login":"a"}}`) }) got, _, err := client.Repositories.Transfer(context.Background(), "o", "r", input) if err != nil { t.Errorf("Repositories.Transfer returned error: %v", err) } want := &Repository{Owner: &User{Login: String("a")}} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.Transfer returned %+v, want %+v", got, want) } } go-github-28.1.1/github/repos_traffic.go000066400000000000000000000105601353501270500201320ustar00rootroot00000000000000// 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" ) // TrafficReferrer represent information about traffic from a referrer . type TrafficReferrer struct { Referrer *string `json:"referrer,omitempty"` Count *int `json:"count,omitempty"` Uniques *int `json:"uniques,omitempty"` } // TrafficPath represent information about the traffic on a path of the repo. type TrafficPath struct { Path *string `json:"path,omitempty"` Title *string `json:"title,omitempty"` Count *int `json:"count,omitempty"` Uniques *int `json:"uniques,omitempty"` } // TrafficData represent information about a specific timestamp in views or clones list. type TrafficData struct { Timestamp *Timestamp `json:"timestamp,omitempty"` Count *int `json:"count,omitempty"` Uniques *int `json:"uniques,omitempty"` } // TrafficViews represent information about the number of views in the last 14 days. type TrafficViews struct { Views []*TrafficData `json:"views,omitempty"` Count *int `json:"count,omitempty"` Uniques *int `json:"uniques,omitempty"` } // TrafficClones represent information about the number of clones in the last 14 days. type TrafficClones struct { Clones []*TrafficData `json:"clones,omitempty"` Count *int `json:"count,omitempty"` Uniques *int `json:"uniques,omitempty"` } // TrafficBreakdownOptions specifies the parameters to methods that support breakdown per day or week. // Can be one of: day, week. Default: day. type TrafficBreakdownOptions struct { Per string `url:"per,omitempty"` } // ListTrafficReferrers list the top 10 referrers over the last 14 days. // // GitHub API docs: https://developer.github.com/v3/repos/traffic/#list-referrers func (s *RepositoriesService) ListTrafficReferrers(ctx context.Context, owner, repo string) ([]*TrafficReferrer, *Response, error) { u := fmt.Sprintf("repos/%v/%v/traffic/popular/referrers", owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var trafficReferrers []*TrafficReferrer resp, err := s.client.Do(ctx, req, &trafficReferrers) if err != nil { return nil, resp, err } return trafficReferrers, resp, nil } // ListTrafficPaths list the top 10 popular content over the last 14 days. // // GitHub API docs: https://developer.github.com/v3/repos/traffic/#list-paths func (s *RepositoriesService) ListTrafficPaths(ctx context.Context, owner, repo string) ([]*TrafficPath, *Response, error) { u := fmt.Sprintf("repos/%v/%v/traffic/popular/paths", owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var paths []*TrafficPath resp, err := s.client.Do(ctx, req, &paths) if err != nil { return nil, resp, err } return paths, resp, nil } // ListTrafficViews get total number of views for the last 14 days and breaks it down either per day or week. // // GitHub API docs: https://developer.github.com/v3/repos/traffic/#views func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo string, opt *TrafficBreakdownOptions) (*TrafficViews, *Response, error) { u := fmt.Sprintf("repos/%v/%v/traffic/views", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } trafficViews := new(TrafficViews) resp, err := s.client.Do(ctx, req, &trafficViews) if err != nil { return nil, resp, err } return trafficViews, resp, nil } // 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 func (s *RepositoriesService) ListTrafficClones(ctx context.Context, owner, repo string, opt *TrafficBreakdownOptions) (*TrafficClones, *Response, error) { u := fmt.Sprintf("repos/%v/%v/traffic/clones", owner, repo) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } trafficClones := new(TrafficClones) resp, err := s.client.Do(ctx, req, &trafficClones) if err != nil { return nil, resp, err } return trafficClones, resp, nil } go-github-28.1.1/github/repos_traffic_test.go000066400000000000000000000201411353501270500211650ustar00rootroot00000000000000// 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" "reflect" "testing" "time" ) func TestRepositoriesService_ListTrafficReferrers(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/traffic/popular/referrers", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprintf(w, `[{ "referrer": "Google", "count": 4, "uniques": 3 }]`) }) ctx := context.Background() got, _, err := client.Repositories.ListTrafficReferrers(ctx, "o", "r") if err != nil { t.Errorf("Repositories.ListTrafficReferrers returned error: %+v", err) } want := []*TrafficReferrer{{ Referrer: String("Google"), Count: Int(4), Uniques: Int(3), }} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ListTrafficReferrers returned %+v, want %+v", got, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Repositories.ListTrafficReferrers(ctx, "o", "r") if got != nil { t.Errorf("client.BaseURL.Path='' ListTrafficReferrers = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' ListTrafficReferrers resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' ListTrafficReferrers err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Repositories.ListTrafficReferrers(ctx, "o", "r") if got != nil { t.Errorf("rate.Reset.Time > now ListTrafficReferrers = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now ListTrafficReferrers resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now ListTrafficReferrers err = nil, want error") } } func TestRepositoriesService_ListTrafficPaths(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/traffic/popular/paths", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprintf(w, `[{ "path": "/github/hubot", "title": "github/hubot: A customizable life embetterment robot.", "count": 3542, "uniques": 2225 }]`) }) ctx := context.Background() got, _, err := client.Repositories.ListTrafficPaths(ctx, "o", "r") if err != nil { t.Errorf("Repositories.ListTrafficPaths returned error: %+v", err) } want := []*TrafficPath{{ Path: String("/github/hubot"), Title: String("github/hubot: A customizable life embetterment robot."), Count: Int(3542), Uniques: Int(2225), }} if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ListTrafficPaths returned %+v, want %+v", got, want) } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Repositories.ListTrafficPaths(ctx, "o", "r") if got != nil { t.Errorf("client.BaseURL.Path='' ListTrafficPaths = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' ListTrafficPaths resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' ListTrafficPaths err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Repositories.ListTrafficPaths(ctx, "o", "r") if got != nil { t.Errorf("rate.Reset.Time > now ListTrafficPaths = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now ListTrafficPaths resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now ListTrafficPaths err = nil, want error") } } func TestRepositoriesService_ListTrafficViews(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/traffic/views", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprintf(w, `{"count": 7, "uniques": 6, "views": [{ "timestamp": "2016-05-31T16:00:00.000Z", "count": 7, "uniques": 6 }]}`) }) ctx := context.Background() got, _, err := client.Repositories.ListTrafficViews(ctx, "o", "r", nil) if err != nil { t.Errorf("Repositories.ListTrafficViews returned error: %+v", err) } want := &TrafficViews{ Views: []*TrafficData{{ Timestamp: &Timestamp{time.Date(2016, time.May, 31, 16, 0, 0, 0, time.UTC)}, Count: Int(7), Uniques: Int(6), }}, Count: Int(7), Uniques: Int(6), } if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ListTrafficViews returned %+v, want %+v", got, want) } // Test addOptions failure _, _, err = client.Repositories.ListTrafficViews(ctx, "\n", "\n", &TrafficBreakdownOptions{}) if err == nil { t.Error("bad options ListTrafficViews err = nil, want error") } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Repositories.ListTrafficViews(ctx, "o", "r", nil) if got != nil { t.Errorf("client.BaseURL.Path='' ListTrafficViews = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' ListTrafficViews resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' ListTrafficViews err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Repositories.ListTrafficViews(ctx, "o", "r", nil) if got != nil { t.Errorf("rate.Reset.Time > now ListTrafficViews = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now ListTrafficViews resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now ListTrafficViews err = nil, want error") } } func TestRepositoriesService_ListTrafficClones(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/traffic/clones", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprintf(w, `{"count": 7, "uniques": 6, "clones": [{ "timestamp": "2016-05-31T16:00:00.00Z", "count": 7, "uniques": 6 }]}`) }) ctx := context.Background() got, _, err := client.Repositories.ListTrafficClones(ctx, "o", "r", nil) if err != nil { t.Errorf("Repositories.ListTrafficClones returned error: %+v", err) } want := &TrafficClones{ Clones: []*TrafficData{{ Timestamp: &Timestamp{time.Date(2016, time.May, 31, 16, 0, 0, 0, time.UTC)}, Count: Int(7), Uniques: Int(6), }}, Count: Int(7), Uniques: Int(6), } if !reflect.DeepEqual(got, want) { t.Errorf("Repositories.ListTrafficClones returned %+v, want %+v", got, want) } // Test addOptions failure _, _, err = client.Repositories.ListTrafficClones(ctx, "\n", "\n", &TrafficBreakdownOptions{}) if err == nil { t.Error("bad options ListTrafficViews err = nil, want error") } // Test s.client.NewRequest failure client.BaseURL.Path = "" got, resp, err := client.Repositories.ListTrafficClones(ctx, "o", "r", nil) if got != nil { t.Errorf("client.BaseURL.Path='' ListTrafficClones = %#v, want nil", got) } if resp != nil { t.Errorf("client.BaseURL.Path='' ListTrafficClones resp = %#v, want nil", resp) } if err == nil { t.Error("client.BaseURL.Path='' ListTrafficClones err = nil, want error") } // Test s.client.Do failure client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) got, resp, err = client.Repositories.ListTrafficClones(ctx, "o", "r", nil) if got != nil { t.Errorf("rate.Reset.Time > now ListTrafficClones = %#v, want nil", got) } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { t.Errorf("rate.Reset.Time > now ListTrafficClones resp = %#v, want StatusCode=%v", resp.Response, want) } if err == nil { t.Error("rate.Reset.Time > now ListTrafficClones err = nil, want error") } } go-github-28.1.1/github/search.go000066400000000000000000000234301353501270500165510ustar00rootroot00000000000000// 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" "strconv" qs "github.com/google/go-querystring/query" ) // SearchService provides access to the search related functions // in the GitHub API. // // Each method takes a query string defining the search keywords and any search qualifiers. // For example, when searching issues, the query "gopher is:issue language:go" will search // for issues containing the word "gopher" in Go repositories. The method call // opts := &github.SearchOptions{Sort: "created", Order: "asc"} // cl.Search.Issues(ctx, "gopher is:issue language:go", opts) // will search for such issues, sorting by creation date in ascending order // (i.e., oldest first). // // GitHub API docs: https://developer.github.com/v3/search/ type SearchService service // SearchOptions specifies optional parameters to the SearchService methods. type SearchOptions struct { // How to sort the search results. Possible values are: // - for repositories: stars, fork, updated // - for commits: author-date, committer-date // - for code: indexed // - for issues: comments, created, updated // - for users: followers, repositories, joined // // Default is to sort by best match. Sort string `url:"sort,omitempty"` // Sort order if sort parameter is provided. Possible values are: asc, // desc. Default is desc. Order string `url:"order,omitempty"` // Whether to retrieve text match metadata with a query TextMatch bool `url:"-"` ListOptions } // Common search parameters. type searchParameters struct { Query string RepositoryID *int64 // Sent if non-nil. } // RepositoriesSearchResult represents the result of a repositories search. type RepositoriesSearchResult struct { Total *int `json:"total_count,omitempty"` IncompleteResults *bool `json:"incomplete_results,omitempty"` Repositories []Repository `json:"items,omitempty"` } // Repositories searches repositories via various criteria. // // GitHub API docs: https://developer.github.com/v3/search/#search-repositories func (s *SearchService) Repositories(ctx context.Context, query string, opt *SearchOptions) (*RepositoriesSearchResult, *Response, error) { result := new(RepositoriesSearchResult) resp, err := s.search(ctx, "repositories", &searchParameters{Query: query}, opt, result) return result, resp, err } // CommitsSearchResult represents the result of a commits search. type CommitsSearchResult struct { Total *int `json:"total_count,omitempty"` IncompleteResults *bool `json:"incomplete_results,omitempty"` Commits []*CommitResult `json:"items,omitempty"` } // CommitResult represents a commit object as returned in commit search endpoint response. type CommitResult struct { SHA *string `json:"sha,omitempty"` Commit *Commit `json:"commit,omitempty"` Author *User `json:"author,omitempty"` Committer *User `json:"committer,omitempty"` Parents []*Commit `json:"parents,omitempty"` HTMLURL *string `json:"html_url,omitempty"` URL *string `json:"url,omitempty"` CommentsURL *string `json:"comments_url,omitempty"` Repository *Repository `json:"repository,omitempty"` Score *float64 `json:"score,omitempty"` } // Commits searches commits via various criteria. // // GitHub API docs: https://developer.github.com/v3/search/#search-commits func (s *SearchService) Commits(ctx context.Context, query string, opt *SearchOptions) (*CommitsSearchResult, *Response, error) { result := new(CommitsSearchResult) resp, err := s.search(ctx, "commits", &searchParameters{Query: query}, opt, result) return result, resp, err } // IssuesSearchResult represents the result of an issues search. type IssuesSearchResult struct { Total *int `json:"total_count,omitempty"` IncompleteResults *bool `json:"incomplete_results,omitempty"` Issues []Issue `json:"items,omitempty"` } // Issues searches issues via various criteria. // // GitHub API docs: https://developer.github.com/v3/search/#search-issues func (s *SearchService) Issues(ctx context.Context, query string, opt *SearchOptions) (*IssuesSearchResult, *Response, error) { result := new(IssuesSearchResult) resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opt, result) return result, resp, err } // UsersSearchResult represents the result of a users search. type UsersSearchResult struct { Total *int `json:"total_count,omitempty"` IncompleteResults *bool `json:"incomplete_results,omitempty"` Users []User `json:"items,omitempty"` } // Users searches users via various criteria. // // GitHub API docs: https://developer.github.com/v3/search/#search-users func (s *SearchService) Users(ctx context.Context, query string, opt *SearchOptions) (*UsersSearchResult, *Response, error) { result := new(UsersSearchResult) resp, err := s.search(ctx, "users", &searchParameters{Query: query}, opt, result) return result, resp, err } // Match represents a single text match. type Match struct { Text *string `json:"text,omitempty"` Indices []int `json:"indices,omitempty"` } // TextMatch represents a text match for a SearchResult type TextMatch struct { ObjectURL *string `json:"object_url,omitempty"` ObjectType *string `json:"object_type,omitempty"` Property *string `json:"property,omitempty"` Fragment *string `json:"fragment,omitempty"` Matches []Match `json:"matches,omitempty"` } func (tm TextMatch) String() string { return Stringify(tm) } // CodeSearchResult represents the result of a code search. type CodeSearchResult struct { Total *int `json:"total_count,omitempty"` IncompleteResults *bool `json:"incomplete_results,omitempty"` CodeResults []CodeResult `json:"items,omitempty"` } // CodeResult represents a single search result. type CodeResult struct { Name *string `json:"name,omitempty"` Path *string `json:"path,omitempty"` SHA *string `json:"sha,omitempty"` HTMLURL *string `json:"html_url,omitempty"` Repository *Repository `json:"repository,omitempty"` TextMatches []TextMatch `json:"text_matches,omitempty"` } func (c CodeResult) String() string { return Stringify(c) } // Code searches code via various criteria. // // GitHub API docs: https://developer.github.com/v3/search/#search-code func (s *SearchService) Code(ctx context.Context, query string, opt *SearchOptions) (*CodeSearchResult, *Response, error) { result := new(CodeSearchResult) resp, err := s.search(ctx, "code", &searchParameters{Query: query}, opt, result) return result, resp, err } // LabelsSearchResult represents the result of a code search. type LabelsSearchResult struct { Total *int `json:"total_count,omitempty"` IncompleteResults *bool `json:"incomplete_results,omitempty"` Labels []*LabelResult `json:"items,omitempty"` } // LabelResult represents a single search result. type LabelResult struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` Name *string `json:"name,omitempty"` Color *string `json:"color,omitempty"` Default *bool `json:"default,omitempty"` Description *string `json:"description,omitempty"` Score *float64 `json:"score,omitempty"` } func (l LabelResult) String() string { return Stringify(l) } // Labels searches labels in the repository with ID repoID via various criteria. // // GitHub API docs: https://developer.github.com/v3/search/#search-labels func (s *SearchService) Labels(ctx context.Context, repoID int64, query string, opt *SearchOptions) (*LabelsSearchResult, *Response, error) { result := new(LabelsSearchResult) resp, err := s.search(ctx, "labels", &searchParameters{RepositoryID: &repoID, Query: query}, opt, result) return result, resp, err } // Helper function that executes search queries against different // GitHub search types (repositories, commits, code, issues, users, labels) // // If searchParameters.Query includes multiple condition, it MUST NOT include "+" as condition separator. // For example, querying with "language:c++" and "leveldb", then searchParameters.Query should be "language:c++ leveldb" but not "language:c+++leveldb". func (s *SearchService) search(ctx context.Context, searchType string, parameters *searchParameters, opt *SearchOptions, result interface{}) (*Response, error) { params, err := qs.Values(opt) if err != nil { return nil, err } if parameters.RepositoryID != nil { params.Set("repository_id", strconv.FormatInt(*parameters.RepositoryID, 10)) } params.Set("q", parameters.Query) u := fmt.Sprintf("search/%s?%s", searchType, params.Encode()) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } switch { case searchType == "commits": // Accept header for search commits preview endpoint // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeCommitSearchPreview) case searchType == "repositories": // Accept header for search repositories based on topics preview endpoint // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTopicsPreview) case searchType == "labels": // Accept header for search labels based on label description preview endpoint. // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) case opt != nil && opt.TextMatch: // Accept header defaults to "application/vnd.github.v3+json" // We change it here to fetch back text-match metadata req.Header.Set("Accept", "application/vnd.github.v3.text-match+json") } return s.client.Do(ctx, req, result) } go-github-28.1.1/github/search_test.go000066400000000000000000000240371353501270500176140ustar00rootroot00000000000000// 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" "net/http" "reflect" "testing" ) func TestSearchService_Repositories(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/search/repositories", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "q": "blah", "sort": "forks", "order": "desc", "page": "2", "per_page": "2", }) fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id":1},{"id":2}]}`) }) opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}} result, _, err := client.Search.Repositories(context.Background(), "blah", opts) if err != nil { t.Errorf("Search.Repositories returned error: %v", err) } want := &RepositoriesSearchResult{ Total: Int(4), IncompleteResults: Bool(false), Repositories: []Repository{{ID: Int64(1)}, {ID: Int64(2)}}, } if !reflect.DeepEqual(result, want) { t.Errorf("Search.Repositories returned %+v, want %+v", result, want) } } func TestSearchService_Commits(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/search/commits", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "q": "blah", "sort": "author-date", "order": "desc", }) fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"sha":"random_hash1"},{"sha":"random_hash2"}]}`) }) opts := &SearchOptions{Sort: "author-date", Order: "desc"} result, _, err := client.Search.Commits(context.Background(), "blah", opts) if err != nil { t.Errorf("Search.Commits returned error: %v", err) } want := &CommitsSearchResult{ Total: Int(4), IncompleteResults: Bool(false), Commits: []*CommitResult{{SHA: String("random_hash1")}, {SHA: String("random_hash2")}}, } if !reflect.DeepEqual(result, want) { t.Errorf("Search.Commits returned %+v, want %+v", result, want) } } func TestSearchService_Issues(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "q": "blah", "sort": "forks", "order": "desc", "page": "2", "per_page": "2", }) fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`) }) opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}} result, _, err := client.Search.Issues(context.Background(), "blah", opts) if err != nil { t.Errorf("Search.Issues returned error: %v", err) } want := &IssuesSearchResult{ Total: Int(4), IncompleteResults: Bool(true), Issues: []Issue{{Number: Int(1)}, {Number: Int(2)}}, } if !reflect.DeepEqual(result, want) { t.Errorf("Search.Issues returned %+v, want %+v", result, want) } } func TestSearchService_Issues_withQualifiersNoOpts(t *testing.T) { client, mux, _, teardown := setup() defer teardown() const q = "gopher is:issue label:bug language:c++ pushed:>=2018-01-01 stars:>=200" var requestURI string mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "q": q, }) requestURI = r.RequestURI fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`) }) opts := &SearchOptions{} result, _, err := client.Search.Issues(context.Background(), q, opts) if err != nil { t.Errorf("Search.Issues returned error: %v", err) } if want := "/api-v3/search/issues?q=gopher+is%3Aissue+label%3Abug+language%3Ac%2B%2B+pushed%3A%3E%3D2018-01-01+stars%3A%3E%3D200"; requestURI != want { t.Fatalf("URI encoding failed: got %v, want %v", requestURI, want) } want := &IssuesSearchResult{ Total: Int(4), IncompleteResults: Bool(true), Issues: []Issue{{Number: Int(1)}, {Number: Int(2)}}, } if !reflect.DeepEqual(result, want) { t.Errorf("Search.Issues returned %+v, want %+v", result, want) } } func TestSearchService_Issues_withQualifiersAndOpts(t *testing.T) { client, mux, _, teardown := setup() defer teardown() const q = "gopher is:issue label:bug language:c++ pushed:>=2018-01-01 stars:>=200" var requestURI string mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "q": q, "sort": "forks", }) requestURI = r.RequestURI fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`) }) opts := &SearchOptions{Sort: "forks"} result, _, err := client.Search.Issues(context.Background(), q, opts) if err != nil { t.Errorf("Search.Issues returned error: %v", err) } if want := "/api-v3/search/issues?q=gopher+is%3Aissue+label%3Abug+language%3Ac%2B%2B+pushed%3A%3E%3D2018-01-01+stars%3A%3E%3D200&sort=forks"; requestURI != want { t.Fatalf("URI encoding failed: got %v, want %v", requestURI, want) } want := &IssuesSearchResult{ Total: Int(4), IncompleteResults: Bool(true), Issues: []Issue{{Number: Int(1)}, {Number: Int(2)}}, } if !reflect.DeepEqual(result, want) { t.Errorf("Search.Issues returned %+v, want %+v", result, want) } } func TestSearchService_Users(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/search/users", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "q": "blah", "sort": "forks", "order": "desc", "page": "2", "per_page": "2", }) fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id":1},{"id":2}]}`) }) opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}} result, _, err := client.Search.Users(context.Background(), "blah", opts) if err != nil { t.Errorf("Search.Issues returned error: %v", err) } want := &UsersSearchResult{ Total: Int(4), IncompleteResults: Bool(false), Users: []User{{ID: Int64(1)}, {ID: Int64(2)}}, } if !reflect.DeepEqual(result, want) { t.Errorf("Search.Users returned %+v, want %+v", result, want) } } func TestSearchService_Code(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/search/code", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "q": "blah", "sort": "forks", "order": "desc", "page": "2", "per_page": "2", }) fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"name":"1"},{"name":"2"}]}`) }) opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}} result, _, err := client.Search.Code(context.Background(), "blah", opts) if err != nil { t.Errorf("Search.Code returned error: %v", err) } want := &CodeSearchResult{ Total: Int(4), IncompleteResults: Bool(false), CodeResults: []CodeResult{{Name: String("1")}, {Name: String("2")}}, } if !reflect.DeepEqual(result, want) { t.Errorf("Search.Code returned %+v, want %+v", result, want) } } func TestSearchService_CodeTextMatch(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/search/code", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") textMatchResponse := ` { "total_count": 1, "incomplete_results": false, "items": [ { "name":"gopher1", "text_matches": [ { "fragment": "I'm afraid my friend what you have found\nIs a gopher who lives to feed", "matches": [ { "text": "gopher", "indices": [ 14, 21 ] } ] } ] } ] } ` fmt.Fprint(w, textMatchResponse) }) opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}, TextMatch: true} result, _, err := client.Search.Code(context.Background(), "blah", opts) if err != nil { t.Errorf("Search.Code returned error: %v", err) } wantedCodeResult := CodeResult{ Name: String("gopher1"), TextMatches: []TextMatch{{ Fragment: String("I'm afraid my friend what you have found\nIs a gopher who lives to feed"), Matches: []Match{{Text: String("gopher"), Indices: []int{14, 21}}}, }, }, } want := &CodeSearchResult{ Total: Int(1), IncompleteResults: Bool(false), CodeResults: []CodeResult{wantedCodeResult}, } if !reflect.DeepEqual(result, want) { t.Errorf("Search.Code returned %+v, want %+v", result, want) } } func TestSearchService_Labels(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/search/labels", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "repository_id": "1234", "q": "blah", "sort": "updated", "order": "desc", "page": "2", "per_page": "2", }) fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id": 1234, "name":"bug", "description": "some text"},{"id": 4567, "name":"feature"}]}`) }) opts := &SearchOptions{Sort: "updated", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}} result, _, err := client.Search.Labels(context.Background(), 1234, "blah", opts) if err != nil { t.Errorf("Search.Code returned error: %v", err) } want := &LabelsSearchResult{ Total: Int(4), IncompleteResults: Bool(false), Labels: []*LabelResult{ {ID: Int64(1234), Name: String("bug"), Description: String("some text")}, {ID: Int64(4567), Name: String("feature")}, }, } if !reflect.DeepEqual(result, want) { t.Errorf("Search.Labels returned %+v, want %+v", result, want) } } go-github-28.1.1/github/strings.go000066400000000000000000000034661353501270500170040ustar00rootroot00000000000000// 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 ( "bytes" "fmt" "io" "reflect" ) var timestampType = reflect.TypeOf(Timestamp{}) // Stringify attempts to create a reasonable string representation of types in // the GitHub library. It does things like resolve pointers to their values // and omits struct fields with nil values. func Stringify(message interface{}) string { var buf bytes.Buffer v := reflect.ValueOf(message) stringifyValue(&buf, v) return buf.String() } // stringifyValue was heavily inspired by the goprotobuf library. func stringifyValue(w io.Writer, val reflect.Value) { if val.Kind() == reflect.Ptr && val.IsNil() { w.Write([]byte("")) return } v := reflect.Indirect(val) switch v.Kind() { case reflect.String: fmt.Fprintf(w, `"%s"`, v) case reflect.Slice: w.Write([]byte{'['}) for i := 0; i < v.Len(); i++ { if i > 0 { w.Write([]byte{' '}) } stringifyValue(w, v.Index(i)) } w.Write([]byte{']'}) return case reflect.Struct: if v.Type().Name() != "" { w.Write([]byte(v.Type().String())) } // special handling of Timestamp values if v.Type() == timestampType { fmt.Fprintf(w, "{%s}", v.Interface()) return } w.Write([]byte{'{'}) var sep bool for i := 0; i < v.NumField(); i++ { fv := v.Field(i) if fv.Kind() == reflect.Ptr && fv.IsNil() { continue } if fv.Kind() == reflect.Slice && fv.IsNil() { continue } if sep { w.Write([]byte(", ")) } else { sep = true } w.Write([]byte(v.Type().Field(i).Name)) w.Write([]byte{':'}) stringifyValue(w, fv) } w.Write([]byte{'}'}) default: if v.CanInterface() { fmt.Fprint(w, v.Interface()) } } } go-github-28.1.1/github/strings_test.go000066400000000000000000000113101353501270500200260ustar00rootroot00000000000000// 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 ( "fmt" "testing" "time" ) func TestStringify(t *testing.T) { var nilPointer *string var tests = []struct { in interface{} out string }{ // basic types {"foo", `"foo"`}, {123, `123`}, {1.5, `1.5`}, {false, `false`}, { []string{"a", "b"}, `["a" "b"]`, }, { struct { A []string }{nil}, // nil slice is skipped `{}`, }, { struct { A string }{"foo"}, // structs not of a named type get no prefix `{A:"foo"}`, }, // pointers {nilPointer, ``}, {String("foo"), `"foo"`}, {Int(123), `123`}, {Bool(false), `false`}, { []*string{String("a"), String("b")}, `["a" "b"]`, }, // actual GitHub structs { Timestamp{time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)}, `github.Timestamp{2006-01-02 15:04:05 +0000 UTC}`, }, { &Timestamp{time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)}, `github.Timestamp{2006-01-02 15:04:05 +0000 UTC}`, }, { User{ID: Int64(123), Name: String("n")}, `github.User{ID:123, Name:"n"}`, }, { Repository{Owner: &User{ID: Int64(123)}}, `github.Repository{Owner:github.User{ID:123}}`, }, } for i, tt := range tests { s := Stringify(tt.in) if s != tt.out { t.Errorf("%d. Stringify(%q) => %q, want %q", i, tt.in, s, tt.out) } } } // Directly test the String() methods on various GitHub types. We don't do an // exaustive test of all the various field types, since TestStringify() above // takes care of that. Rather, we just make sure that Stringify() is being // used to build the strings, which we do by verifying that pointers are // stringified as their underlying value. func TestString(t *testing.T) { var tests = []struct { in interface{} out string }{ {CodeResult{Name: String("n")}, `github.CodeResult{Name:"n"}`}, {CommitAuthor{Name: String("n")}, `github.CommitAuthor{Name:"n"}`}, {CommitFile{SHA: String("s")}, `github.CommitFile{SHA:"s"}`}, {CommitStats{Total: Int(1)}, `github.CommitStats{Total:1}`}, {CommitsComparison{TotalCommits: Int(1)}, `github.CommitsComparison{TotalCommits:1}`}, {Commit{SHA: String("s")}, `github.Commit{SHA:"s"}`}, {Event{ID: String("1")}, `github.Event{ID:"1"}`}, {GistComment{ID: Int64(1)}, `github.GistComment{ID:1}`}, {GistFile{Size: Int(1)}, `github.GistFile{Size:1}`}, {Gist{ID: String("1")}, `github.Gist{ID:"1", Files:map[]}`}, {GitObject{SHA: String("s")}, `github.GitObject{SHA:"s"}`}, {Gitignore{Name: String("n")}, `github.Gitignore{Name:"n"}`}, {Hook{ID: Int64(1)}, `github.Hook{ID:1, Config:map[]}`}, {IssueComment{ID: Int64(1)}, `github.IssueComment{ID:1}`}, {Issue{Number: Int(1)}, `github.Issue{Number:1}`}, {Key{ID: Int64(1)}, `github.Key{ID:1}`}, {Label{ID: Int64(1), Name: String("l")}, `github.Label{ID:1, Name:"l"}`}, {Organization{ID: Int64(1)}, `github.Organization{ID:1}`}, {PullRequestComment{ID: Int64(1)}, `github.PullRequestComment{ID:1}`}, {PullRequest{Number: Int(1)}, `github.PullRequest{Number:1}`}, {PullRequestReview{ID: Int64(1)}, `github.PullRequestReview{ID:1}`}, {DraftReviewComment{Position: Int(1)}, `github.DraftReviewComment{Position:1}`}, {PullRequestReviewRequest{Body: String("r")}, `github.PullRequestReviewRequest{Body:"r"}`}, {PullRequestReviewDismissalRequest{Message: String("r")}, `github.PullRequestReviewDismissalRequest{Message:"r"}`}, {PushEventCommit{SHA: String("s")}, `github.PushEventCommit{SHA:"s"}`}, {PushEvent{PushID: Int64(1)}, `github.PushEvent{PushID:1}`}, {Reference{Ref: String("r")}, `github.Reference{Ref:"r"}`}, {ReleaseAsset{ID: Int64(1)}, `github.ReleaseAsset{ID:1}`}, {RepoStatus{ID: Int64(1)}, `github.RepoStatus{ID:1}`}, {RepositoryComment{ID: Int64(1)}, `github.RepositoryComment{ID:1}`}, {RepositoryCommit{SHA: String("s")}, `github.RepositoryCommit{SHA:"s"}`}, {RepositoryContent{Name: String("n")}, `github.RepositoryContent{Name:"n"}`}, {RepositoryRelease{ID: Int64(1)}, `github.RepositoryRelease{ID:1}`}, {Repository{ID: Int64(1)}, `github.Repository{ID:1}`}, {Team{ID: Int64(1)}, `github.Team{ID:1}`}, {TreeEntry{SHA: String("s")}, `github.TreeEntry{SHA:"s"}`}, {Tree{SHA: String("s")}, `github.Tree{SHA:"s"}`}, {User{ID: Int64(1)}, `github.User{ID:1}`}, {WebHookAuthor{Name: String("n")}, `github.WebHookAuthor{Name:"n"}`}, {WebHookCommit{ID: String("1")}, `github.WebHookCommit{ID:"1"}`}, {WebHookPayload{Ref: String("r")}, `github.WebHookPayload{Ref:"r"}`}, } for i, tt := range tests { s := tt.in.(fmt.Stringer).String() if s != tt.out { t.Errorf("%d. String() => %q, want %q", i, tt.in, tt.out) } } } go-github-28.1.1/github/teams.go000066400000000000000000000444541353501270500164260ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "strings" "time" ) // TeamsService provides access to the team-related functions // in the GitHub API. // // GitHub API docs: https://developer.github.com/v3/teams/ type TeamsService service // Team represents a team within a GitHub organization. Teams are used to // manage access to an organization's repositories. type Team struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` Name *string `json:"name,omitempty"` Description *string `json:"description,omitempty"` URL *string `json:"url,omitempty"` Slug *string `json:"slug,omitempty"` // Permission specifies the default permission for repositories owned by the team. Permission *string `json:"permission,omitempty"` // Privacy identifies the level of privacy this team should have. // Possible values are: // secret - only visible to organization owners and members of this team // closed - visible to all members of this organization // Default is "secret". Privacy *string `json:"privacy,omitempty"` MembersCount *int `json:"members_count,omitempty"` ReposCount *int `json:"repos_count,omitempty"` Organization *Organization `json:"organization,omitempty"` MembersURL *string `json:"members_url,omitempty"` RepositoriesURL *string `json:"repositories_url,omitempty"` Parent *Team `json:"parent,omitempty"` // LDAPDN is only available in GitHub Enterprise and when the team // membership is synchronized with LDAP. LDAPDN *string `json:"ldap_dn,omitempty"` } func (t Team) String() string { return Stringify(t) } // Invitation represents a team member's invitation status. type Invitation struct { ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` Login *string `json:"login,omitempty"` Email *string `json:"email,omitempty"` // Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'. Role *string `json:"role,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` Inviter *User `json:"inviter,omitempty"` TeamCount *int `json:"team_count,omitempty"` InvitationTeamURL *string `json:"invitation_team_url,omitempty"` } func (i Invitation) String() string { return Stringify(i) } // ListTeams lists all of the teams for an organization. // // GitHub API docs: https://developer.github.com/v3/teams/#list-teams func (s *TeamsService) ListTeams(ctx context.Context, org string, opt *ListOptions) ([]*Team, *Response, error) { u := fmt.Sprintf("orgs/%v/teams", org) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeNestedTeamsPreview) var teams []*Team resp, err := s.client.Do(ctx, req, &teams) if err != nil { return nil, resp, err } return teams, resp, nil } // GetTeam fetches a team by ID. // // GitHub API docs: https://developer.github.com/v3/teams/#get-team func (s *TeamsService) GetTeam(ctx context.Context, team int64) (*Team, *Response, error) { u := fmt.Sprintf("teams/%v", team) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeNestedTeamsPreview) t := new(Team) resp, err := s.client.Do(ctx, req, t) if err != nil { return nil, resp, err } return t, resp, nil } // GetTeamBySlug fetches a team by slug. // // GitHub API docs: https://developer.github.com/v3/teams/#get-team-by-name func (s *TeamsService) GetTeamBySlug(ctx context.Context, org, slug string) (*Team, *Response, error) { u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } t := new(Team) resp, err := s.client.Do(ctx, req, t) if err != nil { return nil, resp, err } return t, resp, nil } // NewTeam represents a team to be created or modified. type NewTeam struct { Name string `json:"name"` // Name of the team. (Required.) Description *string `json:"description,omitempty"` Maintainers []string `json:"maintainers,omitempty"` RepoNames []string `json:"repo_names,omitempty"` ParentTeamID *int64 `json:"parent_team_id,omitempty"` // Deprecated: Permission is deprecated when creating or editing a team in an org // using the new GitHub permission model. It no longer identifies the // permission a team has on its repos, but only specifies the default // permission a repo is initially added with. Avoid confusion by // specifying a permission value when calling AddTeamRepo. Permission *string `json:"permission,omitempty"` // Privacy identifies the level of privacy this team should have. // Possible values are: // secret - only visible to organization owners and members of this team // closed - visible to all members of this organization // Default is "secret". Privacy *string `json:"privacy,omitempty"` // LDAPDN may be used in GitHub Enterprise when the team membership // is synchronized with LDAP. LDAPDN *string `json:"ldap_dn,omitempty"` } func (s NewTeam) String() string { return Stringify(s) } // CreateTeam creates a new team within an organization. // // GitHub API docs: https://developer.github.com/v3/teams/#create-team func (s *TeamsService) CreateTeam(ctx context.Context, org string, team NewTeam) (*Team, *Response, error) { u := fmt.Sprintf("orgs/%v/teams", org) req, err := s.client.NewRequest("POST", u, team) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeNestedTeamsPreview) t := new(Team) resp, err := s.client.Do(ctx, req, t) if err != nil { return nil, resp, err } return t, resp, nil } // EditTeam edits a team. // // GitHub API docs: https://developer.github.com/v3/teams/#edit-team func (s *TeamsService) EditTeam(ctx context.Context, id int64, team NewTeam) (*Team, *Response, error) { u := fmt.Sprintf("teams/%v", id) req, err := s.client.NewRequest("PATCH", u, team) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeNestedTeamsPreview) t := new(Team) resp, err := s.client.Do(ctx, req, t) if err != nil { return nil, resp, err } return t, resp, nil } // DeleteTeam deletes a team. // // GitHub API docs: https://developer.github.com/v3/teams/#delete-team func (s *TeamsService) DeleteTeam(ctx context.Context, team int64) (*Response, error) { u := fmt.Sprintf("teams/%v", team) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } req.Header.Set("Accept", mediaTypeNestedTeamsPreview) return s.client.Do(ctx, req, nil) } // ListChildTeams lists child teams for a team. // // GitHub API docs: https://developer.github.com/v3/teams/#list-child-teams func (s *TeamsService) ListChildTeams(ctx context.Context, teamID int64, opt *ListOptions) ([]*Team, *Response, error) { u := fmt.Sprintf("teams/%v/teams", teamID) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeNestedTeamsPreview) var teams []*Team resp, err := s.client.Do(ctx, req, &teams) if err != nil { return nil, resp, err } return teams, resp, nil } // ListTeamRepos lists the repositories that the specified team has access to. // // GitHub API docs: https://developer.github.com/v3/teams/#list-team-repos func (s *TeamsService) ListTeamRepos(ctx context.Context, team int64, opt *ListOptions) ([]*Repository, *Response, error) { u := fmt.Sprintf("teams/%v/repos", team) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when topics API fully launches. headers := []string{mediaTypeTopicsPreview, mediaTypeNestedTeamsPreview} req.Header.Set("Accept", strings.Join(headers, ", ")) var repos []*Repository resp, err := s.client.Do(ctx, req, &repos) if err != nil { return nil, resp, err } return repos, resp, nil } // IsTeamRepo checks if a team manages the specified repository. If the // repository is managed by team, a Repository is returned which includes the // permissions team has for that repo. // // GitHub API docs: https://developer.github.com/v3/teams/#check-if-a-team-manages-a-repository func (s *TeamsService) IsTeamRepo(ctx context.Context, team int64, owner string, repo string) (*Repository, *Response, error) { u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } headers := []string{mediaTypeOrgPermissionRepo, mediaTypeNestedTeamsPreview} req.Header.Set("Accept", strings.Join(headers, ", ")) repository := new(Repository) resp, err := s.client.Do(ctx, req, repository) if err != nil { return nil, resp, err } return repository, resp, nil } // TeamAddTeamRepoOptions specifies the optional parameters to the // TeamsService.AddTeamRepo method. type TeamAddTeamRepoOptions struct { // Permission specifies the permission to grant the team on this repository. // Possible values are: // pull - team members can pull, but not push to or administer this repository // push - team members can pull and push, but not administer this repository // admin - team members can pull, push and administer this repository // // If not specified, the team's permission attribute will be used. Permission string `json:"permission,omitempty"` } // AddTeamRepo adds a repository to be managed by the specified team. The // specified repository must be owned by the organization to which the team // belongs, or a direct fork of a repository owned by the organization. // // GitHub API docs: https://developer.github.com/v3/teams/#add-team-repo func (s *TeamsService) AddTeamRepo(ctx context.Context, team int64, owner string, repo string, opt *TeamAddTeamRepoOptions) (*Response, error) { u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // RemoveTeamRepo removes a repository from being managed by the specified // team. Note that this does not delete the repository, it just removes it // from the team. // // GitHub API docs: https://developer.github.com/v3/teams/#remove-team-repo func (s *TeamsService) RemoveTeamRepo(ctx context.Context, team int64, owner string, repo string) (*Response, error) { u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // ListUserTeams lists a user's teams // GitHub API docs: https://developer.github.com/v3/teams/#list-user-teams func (s *TeamsService) ListUserTeams(ctx context.Context, opt *ListOptions) ([]*Team, *Response, error) { u := "user/teams" u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeNestedTeamsPreview) var teams []*Team resp, err := s.client.Do(ctx, req, &teams) if err != nil { return nil, resp, err } return teams, resp, nil } // ListTeamProjects lists the organization projects for a team. // // GitHub API docs: https://developer.github.com/v3/teams/#list-team-projects func (s *TeamsService) ListTeamProjects(ctx context.Context, teamID int64) ([]*Project, *Response, error) { u := fmt.Sprintf("teams/%v/projects", teamID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var projects []*Project resp, err := s.client.Do(ctx, req, &projects) if err != nil { return nil, resp, err } return projects, resp, nil } // ReviewTeamProjects checks whether a team has read, write, or admin // permissions for an organization project. // // GitHub API docs: https://developer.github.com/v3/teams/#review-a-team-project func (s *TeamsService) ReviewTeamProjects(ctx context.Context, teamID, projectID int64) (*Project, *Response, error) { u := fmt.Sprintf("teams/%v/projects/%v", teamID, projectID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) projects := &Project{} resp, err := s.client.Do(ctx, req, &projects) if err != nil { return nil, resp, err } return projects, resp, nil } // TeamProjectOptions specifies the optional parameters to the // TeamsService.AddTeamProject method. type TeamProjectOptions struct { // Permission specifies the permission to grant to the team for this project. // Possible values are: // "read" - team members can read, but not write to or administer this project. // "write" - team members can read and write, but not administer this project. // "admin" - team members can read, write and administer this project. // Permission *string `json:"permission,omitempty"` } // AddTeamProject adds an organization project to a team. To add a project to a team or // update the team's permission on a project, the authenticated user must have admin // permissions for the project. // // GitHub API docs: https://developer.github.com/v3/teams/#add-or-update-team-project func (s *TeamsService) AddTeamProject(ctx context.Context, teamID, projectID int64, opt *TeamProjectOptions) (*Response, error) { u := fmt.Sprintf("teams/%v/projects/%v", teamID, projectID) req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) return s.client.Do(ctx, req, nil) } // RemoveTeamProject removes an organization project from a team. An organization owner or // a team maintainer can remove any project from the team. To remove a project from a team // as an organization member, the authenticated user must have "read" access to both the team // and project, or "admin" access to the team or project. // Note: This endpoint removes the project from the team, but does not delete it. // // GitHub API docs: https://developer.github.com/v3/teams/#remove-team-project func (s *TeamsService) RemoveTeamProject(ctx context.Context, teamID int64, projectID int64) (*Response, error) { u := fmt.Sprintf("teams/%v/projects/%v", teamID, projectID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. acceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview} req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) return s.client.Do(ctx, req, nil) } // IDPGroupList represents a list of external identity provider (IDP) groups. type IDPGroupList struct { Groups []*IDPGroup `json:"groups,omitempty"` } // IDPGroup represents an external identity provider (IDP) group. type IDPGroup struct { GroupID *string `json:"group_id,omitempty"` GroupName *string `json:"group_name,omitempty"` GroupDescription *string `json:"group_description,omitempty"` } // ListIDPGroupsInOrganization lists IDP groups available in an organization. // // GitHub API docs: https://developer.github.com/v3/teams/team_sync/#list-idp-groups-in-an-organization func (s *TeamsService) ListIDPGroupsInOrganization(ctx context.Context, org string, opt *ListOptions) (*IDPGroupList, *Response, error) { u := fmt.Sprintf("orgs/%v/team-sync/groups", org) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamSyncPreview) groups := new(IDPGroupList) resp, err := s.client.Do(ctx, req, groups) if err != nil { return nil, resp, err } return groups, resp, nil } // 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 func (s *TeamsService) ListIDPGroupsForTeam(ctx context.Context, teamID string) (*IDPGroupList, *Response, error) { u := fmt.Sprintf("teams/%v/team-sync/group-mappings", teamID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamSyncPreview) groups := new(IDPGroupList) resp, err := s.client.Do(ctx, req, groups) if err != nil { return nil, resp, err } return groups, resp, err } // 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 func (s *TeamsService) CreateOrUpdateIDPGroupConnections(ctx context.Context, teamID string, opt IDPGroupList) (*IDPGroupList, *Response, error) { u := fmt.Sprintf("teams/%v/team-sync/group-mappings", teamID) req, err := s.client.NewRequest("PATCH", u, opt) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamSyncPreview) groups := new(IDPGroupList) resp, err := s.client.Do(ctx, req, groups) if err != nil { return nil, resp, err } return groups, resp, nil } go-github-28.1.1/github/teams_discussion_comments.go000066400000000000000000000131231353501270500225630ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" ) // DiscussionComment represents a GitHub dicussion in a team. type DiscussionComment struct { Author *User `json:"author,omitempty"` Body *string `json:"body,omitempty"` BodyHTML *string `json:"body_html,omitempty"` BodyVersion *string `json:"body_version,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` DiscussionURL *string `json:"discussion_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` NodeID *string `json:"node_id,omitempty"` Number *int `json:"number,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` URL *string `json:"url,omitempty"` Reactions *Reactions `json:"reactions,omitempty"` } func (c DiscussionComment) String() string { return Stringify(c) } // DiscussionCommentListOptions specifies optional parameters to the // TeamServices.ListComments method. type DiscussionCommentListOptions struct { // Sorts the discussion comments by the date they were created. // Accepted values are asc and desc. Default is desc. Direction string `url:"direction,omitempty"` } // ListComments lists all comments on a team discussion. // Authenticated user must grant read:discussion scope. // // GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#list-comments func (s *TeamsService) ListComments(ctx context.Context, teamID int64, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v/comments", teamID, discussionNumber) u, err := addOptions(u, options) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) var comments []*DiscussionComment resp, err := s.client.Do(ctx, req, &comments) if err != nil { return nil, resp, err } return comments, resp, nil } // GetComment gets a specific comment on a team discussion. // Authenticated user must grant read:discussion scope. // // GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#get-a-single-comment func (s *TeamsService) GetComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) discussionComment := &DiscussionComment{} resp, err := s.client.Do(ctx, req, discussionComment) if err != nil { return nil, resp, err } return discussionComment, resp, nil } // CreateComment creates a new discussion post on a team discussion. // Authenticated user must grant write:discussion scope. // // GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#create-a-comment func (s *TeamsService) CreateComment(ctx context.Context, teamID int64, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v/comments", teamID, discsusionNumber) req, err := s.client.NewRequest("POST", u, comment) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) discussionComment := &DiscussionComment{} resp, err := s.client.Do(ctx, req, discussionComment) if err != nil { return nil, resp, err } return discussionComment, resp, nil } // EditComment edits the body text of a discussion comment. // Authenticated user must grant write:discussion scope. // User is allowed to edit body of a comment only. // // GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#edit-a-comment func (s *TeamsService) EditComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber) req, err := s.client.NewRequest("PATCH", u, comment) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) discussionComment := &DiscussionComment{} resp, err := s.client.Do(ctx, req, discussionComment) if err != nil { return nil, resp, err } return discussionComment, resp, nil } // DeleteComment deletes a comment on a team discussion. // Authenticated user must grant write:discussion scope. // // GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#delete-a-comment func (s *TeamsService) DeleteComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int) (*Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/teams_discussion_comments_test.go000066400000000000000000000157141353501270500236320ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" "time" ) func TestTeamsService_ListComments(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/2/discussions/3/comments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview) testFormValues(t, r, values{ "direction": "desc", }) fmt.Fprintf(w, `[ { "author": { "login": "author", "id": 0, "avatar_url": "https://avatars1.githubusercontent.com/u/0?v=4", "gravatar_id": "", "url": "https://api.github.com/users/author", "html_url": "https://github.com/author", "followers_url": "https://api.github.com/users/author/followers", "following_url": "https://api.github.com/users/author/following{/other_user}", "gists_url": "https://api.github.com/users/author/gists{/gist_id}", "starred_url": "https://api.github.com/users/author/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/author/subscriptions", "organizations_url": "https://api.github.com/users/author/orgs", "repos_url": "https://api.github.com/users/author/repos", "events_url": "https://api.github.com/users/author/events{/privacy}", "received_events_url": "https://api.github.com/users/author/received_events", "type": "User", "site_admin": false }, "body": "comment", "body_html": "

comment

", "body_version": "version", "created_at": "2018-01-01T00:00:00Z", "last_edited_at": null, "discussion_url": "https://api.github.com/teams/2/discussions/3", "html_url": "https://github.com/orgs/1/teams/2/discussions/3/comments/4", "node_id": "node", "number": 4, "updated_at": "2018-01-01T00:00:00Z", "url": "https://api.github.com/teams/2/discussions/3/comments/4" } ]`) }) comments, _, err := client.Teams.ListComments(context.Background(), 2, 3, &DiscussionCommentListOptions{"desc"}) if err != nil { t.Errorf("Teams.ListComments returned error: %v", err) } want := []*DiscussionComment{ { Author: &User{ Login: String("author"), ID: Int64(0), AvatarURL: String("https://avatars1.githubusercontent.com/u/0?v=4"), GravatarID: String(""), URL: String("https://api.github.com/users/author"), HTMLURL: String("https://github.com/author"), FollowersURL: String("https://api.github.com/users/author/followers"), FollowingURL: String("https://api.github.com/users/author/following{/other_user}"), GistsURL: String("https://api.github.com/users/author/gists{/gist_id}"), StarredURL: String("https://api.github.com/users/author/starred{/owner}{/repo}"), SubscriptionsURL: String("https://api.github.com/users/author/subscriptions"), OrganizationsURL: String("https://api.github.com/users/author/orgs"), ReposURL: String("https://api.github.com/users/author/repos"), EventsURL: String("https://api.github.com/users/author/events{/privacy}"), ReceivedEventsURL: String("https://api.github.com/users/author/received_events"), Type: String("User"), SiteAdmin: Bool(false), }, Body: String("comment"), BodyHTML: String("

comment

"), BodyVersion: String("version"), CreatedAt: &Timestamp{time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)}, LastEditedAt: nil, DiscussionURL: String("https://api.github.com/teams/2/discussions/3"), HTMLURL: String("https://github.com/orgs/1/teams/2/discussions/3/comments/4"), NodeID: String("node"), Number: Int(4), UpdatedAt: &Timestamp{time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)}, URL: String("https://api.github.com/teams/2/discussions/3/comments/4"), }, } if !reflect.DeepEqual(comments, want) { t.Errorf("Teams.ListComments returned %+v, want %+v", comments, want) } } func TestTeamsService_GetComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/2/discussions/3/comments/4", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview) fmt.Fprint(w, `{"number":4}`) }) comment, _, err := client.Teams.GetComment(context.Background(), 2, 3, 4) if err != nil { t.Errorf("Teams.GetComment returned error: %v", err) } want := &DiscussionComment{Number: Int(4)} if !reflect.DeepEqual(comment, want) { t.Errorf("Teams.GetComment returned %+v, want %+v", comment, want) } } func TestTeamsService_CreateComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := DiscussionComment{Body: String("c")} mux.HandleFunc("/teams/2/discussions/3/comments", func(w http.ResponseWriter, r *http.Request) { v := new(DiscussionComment) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview) if !reflect.DeepEqual(v, &input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"number":4}`) }) comment, _, err := client.Teams.CreateComment(context.Background(), 2, 3, input) if err != nil { t.Errorf("Teams.CreateComment returned error: %v", err) } want := &DiscussionComment{Number: Int(4)} if !reflect.DeepEqual(comment, want) { t.Errorf("Teams.CreateComment returned %+v, want %+v", comment, want) } } func TestTeamsService_EditComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := DiscussionComment{Body: String("e")} mux.HandleFunc("/teams/2/discussions/3/comments/4", func(w http.ResponseWriter, r *http.Request) { v := new(DiscussionComment) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview) if !reflect.DeepEqual(v, &input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"number":4}`) }) comment, _, err := client.Teams.EditComment(context.Background(), 2, 3, 4, input) if err != nil { t.Errorf("Teams.EditComment returned error: %v", err) } want := &DiscussionComment{Number: Int(4)} if !reflect.DeepEqual(comment, want) { t.Errorf("Teams.EditComment returned %+v, want %+v", comment, want) } } func TestTeamsService_DeleteComment(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/2/discussions/3/comments/4", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview) }) _, err := client.Teams.DeleteComment(context.Background(), 2, 3, 4) if err != nil { t.Errorf("Teams.DeleteComment returned error: %v", err) } } go-github-28.1.1/github/teams_discussions.go000066400000000000000000000131171353501270500210440ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" ) // TeamDiscussion represents a GitHub dicussion in a team. type TeamDiscussion struct { Author *User `json:"author,omitempty"` Body *string `json:"body,omitempty"` BodyHTML *string `json:"body_html,omitempty"` BodyVersion *string `json:"body_version,omitempty"` CommentsCount *int `json:"comments_count,omitempty"` CommentsURL *string `json:"comments_url,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` HTMLURL *string `json:"html_url,omitempty"` NodeID *string `json:"node_id,omitempty"` Number *int `json:"number,omitempty"` Pinned *bool `json:"pinned,omitempty"` Private *bool `json:"private,omitempty"` TeamURL *string `json:"team_url,omitempty"` Title *string `json:"title,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` URL *string `json:"url,omitempty"` Reactions *Reactions `json:"reactions,omitempty"` } func (d TeamDiscussion) String() string { return Stringify(d) } // DiscussionListOptions specifies optional parameters to the // TeamServices.ListDiscussions method. type DiscussionListOptions struct { // Sorts the discussion by the date they were created. // Accepted values are asc and desc. Default is desc. Direction string `url:"direction,omitempty"` } // ListDiscussions lists all discussions on team's page. // Authenticated user must grant read:discussion scope. // // GitHub API docs: https://developer.github.com/v3/teams/discussions/#list-discussions func (s *TeamsService) ListDiscussions(ctx context.Context, teamID int64, options *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) { u := fmt.Sprintf("teams/%v/discussions", teamID) u, err := addOptions(u, options) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) var teamDiscussions []*TeamDiscussion resp, err := s.client.Do(ctx, req, &teamDiscussions) if err != nil { return nil, resp, err } return teamDiscussions, resp, nil } // GetDiscussion gets a specific discussion on a team's page. // Authenticated user must grant read:discussion scope. // // GitHub API docs: https://developer.github.com/v3/teams/discussions/#get-a-single-discussion func (s *TeamsService) GetDiscussion(ctx context.Context, teamID int64, discussionNumber int) (*TeamDiscussion, *Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) teamDiscussion := &TeamDiscussion{} resp, err := s.client.Do(ctx, req, teamDiscussion) if err != nil { return nil, resp, err } return teamDiscussion, resp, nil } // CreateDiscussion creates a new discussion post on a team's page. // Authenticated user must grant write:discussion scope. // // GitHub API docs: https://developer.github.com/v3/teams/discussions/#create-a-discussion func (s *TeamsService) CreateDiscussion(ctx context.Context, teamID int64, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { u := fmt.Sprintf("teams/%v/discussions", teamID) req, err := s.client.NewRequest("POST", u, discussion) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) teamDiscussion := &TeamDiscussion{} resp, err := s.client.Do(ctx, req, teamDiscussion) if err != nil { return nil, resp, err } return teamDiscussion, resp, nil } // EditDiscussion edits the title and body text of a discussion post. // Authenticated user must grant write:discussion scope. // User is allowed to change Title and Body of a discussion only. // // GitHub API docs: https://developer.github.com/v3/teams/discussions/#edit-a-discussion func (s *TeamsService) EditDiscussion(ctx context.Context, teamID int64, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber) req, err := s.client.NewRequest("PATCH", u, discussion) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) teamDiscussion := &TeamDiscussion{} resp, err := s.client.Do(ctx, req, teamDiscussion) if err != nil { return nil, resp, err } return teamDiscussion, resp, nil } // DeleteDiscussion deletes a discussion from team's page. // Authenticated user must grant write:discussion scope. // // GitHub API docs: https://developer.github.com/v3/teams/discussions/#delete-a-discussion func (s *TeamsService) DeleteDiscussion(ctx context.Context, teamID int64, discussionNumber int) (*Response, error) { u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/teams_discussions_test.go000066400000000000000000000163771353501270500221160ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" "time" ) func TestTeamsService_ListDiscussions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/2/discussions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview) testFormValues(t, r, values{ "direction": "desc", }) fmt.Fprintf(w, `[ { "author": { "login": "author", "id": 0, "avatar_url": "https://avatars1.githubusercontent.com/u/0?v=4", "gravatar_id": "", "url": "https://api.github.com/users/author", "html_url": "https://github.com/author", "followers_url": "https://api.github.com/users/author/followers", "following_url": "https://api.github.com/users/author/following{/other_user}", "gists_url": "https://api.github.com/users/author/gists{/gist_id}", "starred_url": "https://api.github.com/users/author/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/author/subscriptions", "organizations_url": "https://api.github.com/users/author/orgs", "repos_url": "https://api.github.com/users/author/repos", "events_url": "https://api.github.com/users/author/events{/privacy}", "received_events_url": "https://api.github.com/users/author/received_events", "type": "User", "site_admin": false }, "body": "test", "body_html": "

test

", "body_version": "version", "comments_count": 1, "comments_url": "https://api.github.com/teams/2/discussions/3/comments", "created_at": "2018-01-01T00:00:00Z", "last_edited_at": null, "html_url": "https://github.com/orgs/1/teams/2/discussions/3", "node_id": "node", "number": 3, "pinned": false, "private": false, "team_url": "https://api.github.com/teams/2", "title": "test", "updated_at": "2018-01-01T00:00:00Z", "url": "https://api.github.com/teams/2/discussions/3" } ]`) }) discussions, _, err := client.Teams.ListDiscussions(context.Background(), 2, &DiscussionListOptions{"desc"}) if err != nil { t.Errorf("Teams.ListDiscussions returned error: %v", err) } want := []*TeamDiscussion{ { Author: &User{ Login: String("author"), ID: Int64(0), AvatarURL: String("https://avatars1.githubusercontent.com/u/0?v=4"), GravatarID: String(""), URL: String("https://api.github.com/users/author"), HTMLURL: String("https://github.com/author"), FollowersURL: String("https://api.github.com/users/author/followers"), FollowingURL: String("https://api.github.com/users/author/following{/other_user}"), GistsURL: String("https://api.github.com/users/author/gists{/gist_id}"), StarredURL: String("https://api.github.com/users/author/starred{/owner}{/repo}"), SubscriptionsURL: String("https://api.github.com/users/author/subscriptions"), OrganizationsURL: String("https://api.github.com/users/author/orgs"), ReposURL: String("https://api.github.com/users/author/repos"), EventsURL: String("https://api.github.com/users/author/events{/privacy}"), ReceivedEventsURL: String("https://api.github.com/users/author/received_events"), Type: String("User"), SiteAdmin: Bool(false), }, Body: String("test"), BodyHTML: String("

test

"), BodyVersion: String("version"), CommentsCount: Int(1), CommentsURL: String("https://api.github.com/teams/2/discussions/3/comments"), CreatedAt: &Timestamp{time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)}, LastEditedAt: nil, HTMLURL: String("https://github.com/orgs/1/teams/2/discussions/3"), NodeID: String("node"), Number: Int(3), Pinned: Bool(false), Private: Bool(false), TeamURL: String("https://api.github.com/teams/2"), Title: String("test"), UpdatedAt: &Timestamp{time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)}, URL: String("https://api.github.com/teams/2/discussions/3"), }, } if !reflect.DeepEqual(discussions, want) { t.Errorf("Teams.ListDiscussions returned %+v, want %+v", discussions, want) } } func TestTeamsService_GetDiscussion(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/2/discussions/3", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview) fmt.Fprint(w, `{"number":3}`) }) discussion, _, err := client.Teams.GetDiscussion(context.Background(), 2, 3) if err != nil { t.Errorf("Teams.GetDiscussion returned error: %v", err) } want := &TeamDiscussion{Number: Int(3)} if !reflect.DeepEqual(discussion, want) { t.Errorf("Teams.GetDiscussion returned %+v, want %+v", discussion, want) } } func TestTeamsService_CreateDiscussion(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := TeamDiscussion{Title: String("c_t"), Body: String("c_b")} mux.HandleFunc("/teams/2/discussions", func(w http.ResponseWriter, r *http.Request) { v := new(TeamDiscussion) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview) if !reflect.DeepEqual(v, &input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"number":3}`) }) comment, _, err := client.Teams.CreateDiscussion(context.Background(), 2, input) if err != nil { t.Errorf("Teams.CreateDiscussion returned error: %v", err) } want := &TeamDiscussion{Number: Int(3)} if !reflect.DeepEqual(comment, want) { t.Errorf("Teams.CreateDiscussion returned %+v, want %+v", comment, want) } } func TestTeamsService_EditDiscussion(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := TeamDiscussion{Title: String("e_t"), Body: String("e_b")} mux.HandleFunc("/teams/2/discussions/3", func(w http.ResponseWriter, r *http.Request) { v := new(TeamDiscussion) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview) if !reflect.DeepEqual(v, &input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"number":3}`) }) comment, _, err := client.Teams.EditDiscussion(context.Background(), 2, 3, input) if err != nil { t.Errorf("Teams.EditDiscussion returned error: %v", err) } want := &TeamDiscussion{Number: Int(3)} if !reflect.DeepEqual(comment, want) { t.Errorf("Teams.EditDiscussion returned %+v, want %+v", comment, want) } } func TestTeamsService_DeleteDiscussion(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/2/discussions/3", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeTeamDiscussionsPreview) }) _, err := client.Teams.DeleteDiscussion(context.Background(), 2, 3) if err != nil { t.Errorf("Teams.DeleteDiscussion returned error: %v", err) } } go-github-28.1.1/github/teams_members.go000066400000000000000000000132541353501270500201320ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" ) // TeamListTeamMembersOptions specifies the optional parameters to the // TeamsService.ListTeamMembers method. type TeamListTeamMembersOptions struct { // Role filters members returned by their role in the team. Possible // values are "all", "member", "maintainer". Default is "all". Role string `url:"role,omitempty"` ListOptions } // ListTeamMembers lists all of the users who are members of the specified // team. // // GitHub API docs: https://developer.github.com/v3/teams/members/#list-team-members func (s *TeamsService) ListTeamMembers(ctx context.Context, team int64, opt *TeamListTeamMembersOptions) ([]*User, *Response, error) { u := fmt.Sprintf("teams/%v/members", team) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeNestedTeamsPreview) var members []*User resp, err := s.client.Do(ctx, req, &members) if err != nil { return nil, resp, err } return members, resp, nil } // IsTeamMember checks if a user is a member of the specified team. // // GitHub API docs: https://developer.github.com/v3/teams/members/#get-team-member // // Deprecated: This API has been marked as deprecated in the Github API docs, // TeamsService.GetTeamMembership method should be used instead. func (s *TeamsService) IsTeamMember(ctx context.Context, team int64, user string) (bool, *Response, error) { u := fmt.Sprintf("teams/%v/members/%v", team, user) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } resp, err := s.client.Do(ctx, req, nil) member, err := parseBoolResponse(err) return member, resp, err } // GetTeamMembership returns the membership status for a user in a team. // // GitHub API docs: https://developer.github.com/v3/teams/members/#get-team-membership func (s *TeamsService) GetTeamMembership(ctx context.Context, team int64, user string) (*Membership, *Response, error) { u := fmt.Sprintf("teams/%v/memberships/%v", team, user) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } req.Header.Set("Accept", mediaTypeNestedTeamsPreview) t := new(Membership) resp, err := s.client.Do(ctx, req, t) if err != nil { return nil, resp, err } return t, resp, nil } // TeamAddTeamMembershipOptions specifies the optional // parameters to the TeamsService.AddTeamMembership method. type TeamAddTeamMembershipOptions struct { // Role specifies the role the user should have in the team. Possible // values are: // member - a normal member of the team // maintainer - a team maintainer. Able to add/remove other team // members, promote other team members to team // maintainer, and edit the team’s name and description // // Default value is "member". Role string `json:"role,omitempty"` } // AddTeamMembership adds or invites a user to a team. // // In order to add a membership between a user and a team, the authenticated // user must have 'admin' permissions to the team or be an owner of the // organization that the team is associated with. // // If the user is already a part of the team's organization (meaning they're on // at least one other team in the organization), this endpoint will add the // user to the team. // // If the user is completely unaffiliated with the team's organization (meaning // they're on none of the organization's teams), this endpoint will send an // invitation to the user via email. This newly-created membership will be in // the "pending" state until the user accepts the invitation, at which point // the membership will transition to the "active" state and the user will be // added as a member of the team. // // GitHub API docs: https://developer.github.com/v3/teams/members/#add-or-update-team-membership func (s *TeamsService) AddTeamMembership(ctx context.Context, team int64, user string, opt *TeamAddTeamMembershipOptions) (*Membership, *Response, error) { u := fmt.Sprintf("teams/%v/memberships/%v", team, user) req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, nil, err } t := new(Membership) resp, err := s.client.Do(ctx, req, t) if err != nil { return nil, resp, err } return t, resp, nil } // RemoveTeamMembership removes a user from a team. // // GitHub API docs: https://developer.github.com/v3/teams/members/#remove-team-membership func (s *TeamsService) RemoveTeamMembership(ctx context.Context, team int64, user string) (*Response, error) { u := fmt.Sprintf("teams/%v/memberships/%v", team, user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // ListPendingTeamInvitations get pending invitaion list in team. // Warning: The API may change without advance notice during the preview period. // Preview features are not supported for production use. // // GitHub API docs: https://developer.github.com/v3/teams/members/#list-pending-team-invitations func (s *TeamsService) ListPendingTeamInvitations(ctx context.Context, team int64, opt *ListOptions) ([]*Invitation, *Response, error) { u := fmt.Sprintf("teams/%v/invitations", team) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var pendingInvitations []*Invitation resp, err := s.client.Do(ctx, req, &pendingInvitations) if err != nil { return nil, resp, err } return pendingInvitations, resp, nil } go-github-28.1.1/github/teams_members_test.go000066400000000000000000000116411353501270500211670ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestTeamsService__ListTeamMembers(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/members", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) testFormValues(t, r, values{"role": "member", "page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &TeamListTeamMembersOptions{Role: "member", ListOptions: ListOptions{Page: 2}} members, _, err := client.Teams.ListTeamMembers(context.Background(), 1, opt) if err != nil { t.Errorf("Teams.ListTeamMembers returned error: %v", err) } want := []*User{{ID: Int64(1)}} if !reflect.DeepEqual(members, want) { t.Errorf("Teams.ListTeamMembers returned %+v, want %+v", members, want) } } func TestTeamsService__IsTeamMember_true(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/members/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") }) member, _, err := client.Teams.IsTeamMember(context.Background(), 1, "u") if err != nil { t.Errorf("Teams.IsTeamMember returned error: %v", err) } if want := true; member != want { t.Errorf("Teams.IsTeamMember returned %+v, want %+v", member, want) } } // ensure that a 404 response is interpreted as "false" and not an error func TestTeamsService__IsTeamMember_false(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/members/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) member, _, err := client.Teams.IsTeamMember(context.Background(), 1, "u") if err != nil { t.Errorf("Teams.IsTeamMember returned error: %+v", err) } if want := false; member != want { t.Errorf("Teams.IsTeamMember returned %+v, want %+v", member, want) } } // ensure that a 400 response is interpreted as an actual error, and not simply // as "false" like the above case of a 404 func TestTeamsService__IsTeamMember_error(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/members/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") http.Error(w, "BadRequest", http.StatusBadRequest) }) member, _, err := client.Teams.IsTeamMember(context.Background(), 1, "u") if err == nil { t.Errorf("Expected HTTP 400 response") } if want := false; member != want { t.Errorf("Teams.IsTeamMember returned %+v, want %+v", member, want) } } func TestTeamsService__IsTeamMember_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Teams.IsTeamMember(context.Background(), 1, "%") testURLParseError(t, err) } func TestTeamsService__GetTeamMembership(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) fmt.Fprint(w, `{"url":"u", "state":"active"}`) }) membership, _, err := client.Teams.GetTeamMembership(context.Background(), 1, "u") if err != nil { t.Errorf("Teams.GetTeamMembership returned error: %v", err) } want := &Membership{URL: String("u"), State: String("active")} if !reflect.DeepEqual(membership, want) { t.Errorf("Teams.GetTeamMembership returned %+v, want %+v", membership, want) } } func TestTeamsService__AddTeamMembership(t *testing.T) { client, mux, _, teardown := setup() defer teardown() opt := &TeamAddTeamMembershipOptions{Role: "maintainer"} mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) { v := new(TeamAddTeamMembershipOptions) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, opt) { t.Errorf("Request body = %+v, want %+v", v, opt) } fmt.Fprint(w, `{"url":"u", "state":"pending"}`) }) membership, _, err := client.Teams.AddTeamMembership(context.Background(), 1, "u", opt) if err != nil { t.Errorf("Teams.AddTeamMembership returned error: %v", err) } want := &Membership{URL: String("u"), State: String("pending")} if !reflect.DeepEqual(membership, want) { t.Errorf("Teams.AddTeamMembership returned %+v, want %+v", membership, want) } } func TestTeamsService__RemoveTeamMembership(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Teams.RemoveTeamMembership(context.Background(), 1, "u") if err != nil { t.Errorf("Teams.RemoveTeamMembership returned error: %v", err) } } go-github-28.1.1/github/teams_test.go000066400000000000000000000536171353501270500174660ustar00rootroot00000000000000// Copyright 2018 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "fmt" "net/http" "reflect" "strings" "testing" "time" ) func TestTeamsService_ListTeams(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/teams", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} teams, _, err := client.Teams.ListTeams(context.Background(), "o", opt) if err != nil { t.Errorf("Teams.ListTeams returned error: %v", err) } want := []*Team{{ID: Int64(1)}} if !reflect.DeepEqual(teams, want) { t.Errorf("Teams.ListTeams returned %+v, want %+v", teams, want) } } func TestTeamsService_ListTeams_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Teams.ListTeams(context.Background(), "%", nil) testURLParseError(t, err) } func TestTeamsService_GetTeam(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) fmt.Fprint(w, `{"id":1, "name":"n", "description": "d", "url":"u", "slug": "s", "permission":"p", "ldap_dn":"cn=n,ou=groups,dc=example,dc=com", "parent":null}`) }) team, _, err := client.Teams.GetTeam(context.Background(), 1) if err != nil { t.Errorf("Teams.GetTeam returned error: %v", err) } want := &Team{ID: Int64(1), Name: String("n"), Description: String("d"), URL: String("u"), Slug: String("s"), Permission: String("p"), LDAPDN: String("cn=n,ou=groups,dc=example,dc=com")} if !reflect.DeepEqual(team, want) { t.Errorf("Teams.GetTeam returned %+v, want %+v", team, want) } } func TestTeamsService_GetTeam_nestedTeams(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) fmt.Fprint(w, `{"id":1, "name":"n", "description": "d", "url":"u", "slug": "s", "permission":"p", "parent": {"id":2, "name":"n", "description": "d", "parent": null}}`) }) team, _, err := client.Teams.GetTeam(context.Background(), 1) if err != nil { t.Errorf("Teams.GetTeam returned error: %v", err) } want := &Team{ID: Int64(1), Name: String("n"), Description: String("d"), URL: String("u"), Slug: String("s"), Permission: String("p"), Parent: &Team{ID: Int64(2), Name: String("n"), Description: String("d")}, } if !reflect.DeepEqual(team, want) { t.Errorf("Teams.GetTeam returned %+v, want %+v", team, want) } } func TestTeamsService_GetTeamBySlug(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/teams/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1, "name":"n", "description": "d", "url":"u", "slug": "s", "permission":"p", "ldap_dn":"cn=n,ou=groups,dc=example,dc=com", "parent":null}`) }) team, _, err := client.Teams.GetTeamBySlug(context.Background(), "o", "s") if err != nil { t.Errorf("Teams.GetTeamBySlug returned error: %v", err) } want := &Team{ID: Int64(1), Name: String("n"), Description: String("d"), URL: String("u"), Slug: String("s"), Permission: String("p"), LDAPDN: String("cn=n,ou=groups,dc=example,dc=com")} if !reflect.DeepEqual(team, want) { t.Errorf("Teams.GetTeamBySlug returned %+v, want %+v", team, want) } } func TestTeamsService_GetTeamBySlug_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Teams.GetTeamBySlug(context.Background(), "%", "s") testURLParseError(t, err) } func TestTeamsService_GetTeamBySlug_notFound(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/teams/s", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) team, resp, err := client.Teams.GetTeamBySlug(context.Background(), "o", "s") if err == nil { t.Errorf("Expected HTTP 404 response") } if got, want := resp.Response.StatusCode, http.StatusNotFound; got != want { t.Errorf("Teams.GetTeamBySlug returned status %d, want %d", got, want) } if team != nil { t.Errorf("Teams.GetTeamBySlug returned %+v, want nil", team) } } func TestTeamsService_CreateTeam(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := NewTeam{Name: "n", Privacy: String("closed"), RepoNames: []string{"r"}} mux.HandleFunc("/orgs/o/teams", func(w http.ResponseWriter, r *http.Request) { v := new(NewTeam) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) if !reflect.DeepEqual(v, &input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) team, _, err := client.Teams.CreateTeam(context.Background(), "o", input) if err != nil { t.Errorf("Teams.CreateTeam returned error: %v", err) } want := &Team{ID: Int64(1)} if !reflect.DeepEqual(team, want) { t.Errorf("Teams.CreateTeam returned %+v, want %+v", team, want) } } func TestTeamsService_CreateTeam_invalidOrg(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Teams.CreateTeam(context.Background(), "%", NewTeam{}) testURLParseError(t, err) } func TestTeamsService_EditTeam(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := NewTeam{Name: "n", Privacy: String("closed")} mux.HandleFunc("/teams/1", func(w http.ResponseWriter, r *http.Request) { v := new(NewTeam) json.NewDecoder(r.Body).Decode(v) testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) testMethod(t, r, "PATCH") if !reflect.DeepEqual(v, &input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) team, _, err := client.Teams.EditTeam(context.Background(), 1, input) if err != nil { t.Errorf("Teams.EditTeam returned error: %v", err) } want := &Team{ID: Int64(1)} if !reflect.DeepEqual(team, want) { t.Errorf("Teams.EditTeam returned %+v, want %+v", team, want) } } func TestTeamsService_DeleteTeam(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) }) _, err := client.Teams.DeleteTeam(context.Background(), 1) if err != nil { t.Errorf("Teams.DeleteTeam returned error: %v", err) } } func TestTeamsService_ListChildTeams(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/teams", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":2}]`) }) opt := &ListOptions{Page: 2} teams, _, err := client.Teams.ListChildTeams(context.Background(), 1, opt) if err != nil { t.Errorf("Teams.ListTeams returned error: %v", err) } want := []*Team{{ID: Int64(2)}} if !reflect.DeepEqual(teams, want) { t.Errorf("Teams.ListTeams returned %+v, want %+v", teams, want) } } func TestTeamsService_ListTeamRepos(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/repos", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") wantAcceptHeaders := []string{mediaTypeTopicsPreview, mediaTypeNestedTeamsPreview} testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} members, _, err := client.Teams.ListTeamRepos(context.Background(), 1, opt) if err != nil { t.Errorf("Teams.ListTeamRepos returned error: %v", err) } want := []*Repository{{ID: Int64(1)}} if !reflect.DeepEqual(members, want) { t.Errorf("Teams.ListTeamRepos returned %+v, want %+v", members, want) } } func TestTeamsService_IsTeamRepo_true(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") wantAcceptHeaders := []string{mediaTypeOrgPermissionRepo, mediaTypeNestedTeamsPreview} testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `{"id":1}`) }) repo, _, err := client.Teams.IsTeamRepo(context.Background(), 1, "o", "r") if err != nil { t.Errorf("Teams.IsTeamRepo returned error: %v", err) } want := &Repository{ID: Int64(1)} if !reflect.DeepEqual(repo, want) { t.Errorf("Teams.IsTeamRepo returned %+v, want %+v", repo, want) } } func TestTeamsService_IsTeamRepo_false(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) repo, resp, err := client.Teams.IsTeamRepo(context.Background(), 1, "o", "r") if err == nil { t.Errorf("Expected HTTP 404 response") } if got, want := resp.Response.StatusCode, http.StatusNotFound; got != want { t.Errorf("Teams.IsTeamRepo returned status %d, want %d", got, want) } if repo != nil { t.Errorf("Teams.IsTeamRepo returned %+v, want nil", repo) } } func TestTeamsService_IsTeamRepo_error(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") http.Error(w, "BadRequest", http.StatusBadRequest) }) repo, resp, err := client.Teams.IsTeamRepo(context.Background(), 1, "o", "r") if err == nil { t.Errorf("Expected HTTP 400 response") } if got, want := resp.Response.StatusCode, http.StatusBadRequest; got != want { t.Errorf("Teams.IsTeamRepo returned status %d, want %d", got, want) } if repo != nil { t.Errorf("Teams.IsTeamRepo returned %+v, want nil", repo) } } func TestTeamsService_IsTeamRepo_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Teams.IsTeamRepo(context.Background(), 1, "%", "r") testURLParseError(t, err) } func TestTeamsService_AddTeamRepo(t *testing.T) { client, mux, _, teardown := setup() defer teardown() opt := &TeamAddTeamRepoOptions{Permission: "admin"} mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) { v := new(TeamAddTeamRepoOptions) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, opt) { t.Errorf("Request body = %+v, want %+v", v, opt) } w.WriteHeader(http.StatusNoContent) }) _, err := client.Teams.AddTeamRepo(context.Background(), 1, "o", "r", opt) if err != nil { t.Errorf("Teams.AddTeamRepo returned error: %v", err) } } func TestTeamsService_AddTeamRepo_noAccess(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") w.WriteHeader(http.StatusUnprocessableEntity) }) _, err := client.Teams.AddTeamRepo(context.Background(), 1, "o", "r", nil) if err == nil { t.Errorf("Expcted error to be returned") } } func TestTeamsService_AddTeamRepo_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Teams.AddTeamRepo(context.Background(), 1, "%", "r", nil) testURLParseError(t, err) } func TestTeamsService_RemoveTeamRepo(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Teams.RemoveTeamRepo(context.Background(), 1, "o", "r") if err != nil { t.Errorf("Teams.RemoveTeamRepo returned error: %v", err) } } func TestTeamsService_RemoveTeamRepo_invalidOwner(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Teams.RemoveTeamRepo(context.Background(), 1, "%", "r") testURLParseError(t, err) } func TestTeamsService_ListUserTeams(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/teams", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeNestedTeamsPreview) testFormValues(t, r, values{"page": "1"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 1} teams, _, err := client.Teams.ListUserTeams(context.Background(), opt) if err != nil { t.Errorf("Teams.ListUserTeams returned error: %v", err) } want := []*Team{{ID: Int64(1)}} if !reflect.DeepEqual(teams, want) { t.Errorf("Teams.ListUserTeams returned %+v, want %+v", teams, want) } } func TestTeamsService_ListPendingTeamInvitations(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/invitations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "1"}) fmt.Fprint(w, `[ { "id": 1, "login": "monalisa", "email": "octocat@github.com", "role": "direct_member", "created_at": "2017-01-21T00:00:00Z", "inviter": { "login": "other_user", "id": 1, "avatar_url": "https://github.com/images/error/other_user_happy.gif", "gravatar_id": "", "url": "https://api.github.com/users/other_user", "html_url": "https://github.com/other_user", "followers_url": "https://api.github.com/users/other_user/followers", "following_url": "https://api.github.com/users/other_user/following/other_user", "gists_url": "https://api.github.com/users/other_user/gists/gist_id", "starred_url": "https://api.github.com/users/other_user/starred/owner/repo", "subscriptions_url": "https://api.github.com/users/other_user/subscriptions", "organizations_url": "https://api.github.com/users/other_user/orgs", "repos_url": "https://api.github.com/users/other_user/repos", "events_url": "https://api.github.com/users/other_user/events/privacy", "received_events_url": "https://api.github.com/users/other_user/received_events/privacy", "type": "User", "site_admin": false } } ]`) }) opt := &ListOptions{Page: 1} invitations, _, err := client.Teams.ListPendingTeamInvitations(context.Background(), 1, opt) if err != nil { t.Errorf("Teams.ListPendingTeamInvitations returned error: %v", err) } createdAt := time.Date(2017, time.January, 21, 0, 0, 0, 0, time.UTC) want := []*Invitation{ { ID: Int64(1), Login: String("monalisa"), Email: String("octocat@github.com"), Role: String("direct_member"), CreatedAt: &createdAt, Inviter: &User{ Login: String("other_user"), ID: Int64(1), AvatarURL: String("https://github.com/images/error/other_user_happy.gif"), GravatarID: String(""), URL: String("https://api.github.com/users/other_user"), HTMLURL: String("https://github.com/other_user"), FollowersURL: String("https://api.github.com/users/other_user/followers"), FollowingURL: String("https://api.github.com/users/other_user/following/other_user"), GistsURL: String("https://api.github.com/users/other_user/gists/gist_id"), StarredURL: String("https://api.github.com/users/other_user/starred/owner/repo"), SubscriptionsURL: String("https://api.github.com/users/other_user/subscriptions"), OrganizationsURL: String("https://api.github.com/users/other_user/orgs"), ReposURL: String("https://api.github.com/users/other_user/repos"), EventsURL: String("https://api.github.com/users/other_user/events/privacy"), ReceivedEventsURL: String("https://api.github.com/users/other_user/received_events/privacy"), Type: String("User"), SiteAdmin: Bool(false), }, }} if !reflect.DeepEqual(invitations, want) { t.Errorf("Teams.ListPendingTeamInvitations returned %+v, want %+v", invitations, want) } } func TestTeamsService_ListProjects(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview} mux.HandleFunc("/teams/1/projects", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `[{"id":1}]`) }) projects, _, err := client.Teams.ListTeamProjects(context.Background(), 1) if err != nil { t.Errorf("Teams.ListTeamProjects returned error: %v", err) } want := []*Project{{ID: Int64(1)}} if !reflect.DeepEqual(projects, want) { t.Errorf("Teams.ListTeamProjects returned %+v, want %+v", projects, want) } } func TestTeamsService_ReviewProjects(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview} mux.HandleFunc("/teams/1/projects/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) fmt.Fprint(w, `{"id":1}`) }) project, _, err := client.Teams.ReviewTeamProjects(context.Background(), 1, 1) if err != nil { t.Errorf("Teams.ReviewTeamProjects returned error: %v", err) } want := &Project{ID: Int64(1)} if !reflect.DeepEqual(project, want) { t.Errorf("Teams.ReviewTeamProjects returned %+v, want %+v", project, want) } } func TestTeamsService_AddTeamProject(t *testing.T) { client, mux, _, teardown := setup() defer teardown() opt := &TeamProjectOptions{ Permission: String("admin"), } wantAcceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview} mux.HandleFunc("/teams/1/projects/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) v := &TeamProjectOptions{} json.NewDecoder(r.Body).Decode(v) if !reflect.DeepEqual(v, opt) { t.Errorf("Request body = %+v, want %+v", v, opt) } w.WriteHeader(http.StatusNoContent) }) _, err := client.Teams.AddTeamProject(context.Background(), 1, 1, opt) if err != nil { t.Errorf("Teams.AddTeamProject returned error: %v", err) } } func TestTeamsService_RemoveTeamProject(t *testing.T) { client, mux, _, teardown := setup() defer teardown() wantAcceptHeaders := []string{mediaTypeNestedTeamsPreview, mediaTypeProjectsPreview} mux.HandleFunc("/teams/1/projects/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) w.WriteHeader(http.StatusNoContent) }) _, err := client.Teams.RemoveTeamProject(context.Background(), 1, 1) if err != nil { t.Errorf("Teams.RemoveTeamProject returned error: %v", err) } } func TestTeamsService_ListIDPGroupsInOrganization(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/orgs/o/team-sync/groups", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeTeamSyncPreview) testFormValues(t, r, values{ "page": "2", }) fmt.Fprint(w, `{"groups": [{"group_id": "1", "group_name": "n", "group_description": "d"}]}`) }) opt := &ListOptions{Page: 2} groups, _, err := client.Teams.ListIDPGroupsInOrganization(context.Background(), "o", opt) if err != nil { t.Errorf("Teams.ListIDPGroupsInOrganization returned error: %v", err) } want := &IDPGroupList{ Groups: []*IDPGroup{ { GroupID: String("1"), GroupName: String("n"), GroupDescription: String("d"), }, }, } if !reflect.DeepEqual(groups, want) { t.Errorf("Teams.ListIDPGroupsInOrganization returned %+v. want %+v", groups, want) } } func TestTeamsService_ListIDPGroupsForTeam(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/team-sync/group-mappings", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeTeamSyncPreview) fmt.Fprint(w, `{"groups": [{"group_id": "1", "group_name": "n", "group_description": "d"}]}`) }) groups, _, err := client.Teams.ListIDPGroupsForTeam(context.Background(), "1") if err != nil { t.Errorf("Teams.ListIDPGroupsForTeam returned error: %v", err) } want := &IDPGroupList{ Groups: []*IDPGroup{ { GroupID: String("1"), GroupName: String("n"), GroupDescription: String("d"), }, }, } if !reflect.DeepEqual(groups, want) { t.Errorf("Teams.ListIDPGroupsForTeam returned %+v. want %+v", groups, want) } } func TestTeamsService_CreateOrUpdateIDPGroupConnections(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/teams/1/team-sync/group-mappings", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") testHeader(t, r, "Accept", mediaTypeTeamSyncPreview) fmt.Fprint(w, `{"groups": [{"group_id": "1", "group_name": "n", "group_description": "d"}]}`) }) input := IDPGroupList{ Groups: []*IDPGroup{ { GroupID: String("1"), GroupName: String("n"), GroupDescription: String("d"), }, }, } groups, _, err := client.Teams.CreateOrUpdateIDPGroupConnections(context.Background(), "1", input) if err != nil { t.Errorf("Teams.CreateOrUpdateIDPGroupConnections returned error: %v", err) } want := &IDPGroupList{ Groups: []*IDPGroup{ { GroupID: String("1"), GroupName: String("n"), GroupDescription: String("d"), }, }, } if !reflect.DeepEqual(groups, want) { t.Errorf("Teams.CreateOrUpdateIDPGroupConnections returned %+v. want %+v", groups, want) } } go-github-28.1.1/github/timestamp.go000066400000000000000000000021211353501270500173010ustar00rootroot00000000000000// 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 ( "strconv" "time" ) // Timestamp represents a time that can be unmarshalled from a JSON string // formatted as either an RFC3339 or Unix timestamp. This is necessary for some // fields since the GitHub API is inconsistent in how it represents times. All // exported methods of time.Time can be called on Timestamp. type Timestamp struct { time.Time } func (t Timestamp) String() string { return t.Time.String() } // UnmarshalJSON implements the json.Unmarshaler interface. // Time is expected in RFC3339 or Unix format. func (t *Timestamp) UnmarshalJSON(data []byte) (err error) { str := string(data) i, err := strconv.ParseInt(str, 10, 64) if err == nil { t.Time = time.Unix(i, 0) } else { t.Time, err = time.Parse(`"`+time.RFC3339+`"`, str) } return } // Equal reports whether t and u are equal based on time.Equal func (t Timestamp) Equal(u Timestamp) bool { return t.Time.Equal(u.Time) } go-github-28.1.1/github/timestamp_test.go000066400000000000000000000132421353501270500203460ustar00rootroot00000000000000// 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 ( "encoding/json" "fmt" "testing" "time" ) const ( emptyTimeStr = `"0001-01-01T00:00:00Z"` referenceTimeStr = `"2006-01-02T15:04:05Z"` referenceTimeStrFractional = `"2006-01-02T15:04:05.000Z"` // This format was returned by the Projects API before October 1, 2017. referenceUnixTimeStr = `1136214245` ) var ( referenceTime = time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC) unixOrigin = time.Unix(0, 0).In(time.UTC) ) func TestTimestamp_Marshal(t *testing.T) { testCases := []struct { desc string data Timestamp want string wantErr bool equal bool }{ {"Reference", Timestamp{referenceTime}, referenceTimeStr, false, true}, {"Empty", Timestamp{}, emptyTimeStr, false, true}, {"Mismatch", Timestamp{}, referenceTimeStr, false, false}, } for _, tc := range testCases { out, err := json.Marshal(tc.data) if gotErr := err != nil; gotErr != tc.wantErr { t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err) } got := string(out) equal := got == tc.want if (got == tc.want) != tc.equal { t.Errorf("%s: got=%s, want=%s, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal) } } } func TestTimestamp_Unmarshal(t *testing.T) { testCases := []struct { desc string data string want Timestamp wantErr bool equal bool }{ {"Reference", referenceTimeStr, Timestamp{referenceTime}, false, true}, {"ReferenceUnix", referenceUnixTimeStr, Timestamp{referenceTime}, false, true}, {"ReferenceFractional", referenceTimeStrFractional, Timestamp{referenceTime}, false, true}, {"Empty", emptyTimeStr, Timestamp{}, false, true}, {"UnixStart", `0`, Timestamp{unixOrigin}, false, true}, {"Mismatch", referenceTimeStr, Timestamp{}, false, false}, {"MismatchUnix", `0`, Timestamp{}, false, false}, {"Invalid", `"asdf"`, Timestamp{referenceTime}, true, false}, } for _, tc := range testCases { var got Timestamp err := json.Unmarshal([]byte(tc.data), &got) if gotErr := err != nil; gotErr != tc.wantErr { t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err) continue } equal := got.Equal(tc.want) if equal != tc.equal { t.Errorf("%s: got=%#v, want=%#v, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal) } } } func TestTimstamp_MarshalReflexivity(t *testing.T) { testCases := []struct { desc string data Timestamp }{ {"Reference", Timestamp{referenceTime}}, {"Empty", Timestamp{}}, } for _, tc := range testCases { data, err := json.Marshal(tc.data) if err != nil { t.Errorf("%s: Marshal err=%v", tc.desc, err) } var got Timestamp err = json.Unmarshal(data, &got) if err != nil { t.Errorf("%s: Unmarshal err=%v", tc.desc, err) } if !got.Equal(tc.data) { t.Errorf("%s: %+v != %+v", tc.desc, got, data) } } } type WrappedTimestamp struct { A int Time Timestamp } func TestWrappedTimstamp_Marshal(t *testing.T) { testCases := []struct { desc string data WrappedTimestamp want string wantErr bool equal bool }{ {"Reference", WrappedTimestamp{0, Timestamp{referenceTime}}, fmt.Sprintf(`{"A":0,"Time":%s}`, referenceTimeStr), false, true}, {"Empty", WrappedTimestamp{}, fmt.Sprintf(`{"A":0,"Time":%s}`, emptyTimeStr), false, true}, {"Mismatch", WrappedTimestamp{}, fmt.Sprintf(`{"A":0,"Time":%s}`, referenceTimeStr), false, false}, } for _, tc := range testCases { out, err := json.Marshal(tc.data) if gotErr := err != nil; gotErr != tc.wantErr { t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err) } got := string(out) equal := got == tc.want if equal != tc.equal { t.Errorf("%s: got=%s, want=%s, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal) } } } func TestWrappedTimstamp_Unmarshal(t *testing.T) { testCases := []struct { desc string data string want WrappedTimestamp wantErr bool equal bool }{ {"Reference", referenceTimeStr, WrappedTimestamp{0, Timestamp{referenceTime}}, false, true}, {"ReferenceUnix", referenceUnixTimeStr, WrappedTimestamp{0, Timestamp{referenceTime}}, false, true}, {"Empty", emptyTimeStr, WrappedTimestamp{0, Timestamp{}}, false, true}, {"UnixStart", `0`, WrappedTimestamp{0, Timestamp{unixOrigin}}, false, true}, {"Mismatch", referenceTimeStr, WrappedTimestamp{0, Timestamp{}}, false, false}, {"MismatchUnix", `0`, WrappedTimestamp{0, Timestamp{}}, false, false}, {"Invalid", `"asdf"`, WrappedTimestamp{0, Timestamp{referenceTime}}, true, false}, } for _, tc := range testCases { var got Timestamp err := json.Unmarshal([]byte(tc.data), &got) if gotErr := err != nil; gotErr != tc.wantErr { t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err) continue } equal := got.Time.Equal(tc.want.Time.Time) if equal != tc.equal { t.Errorf("%s: got=%#v, want=%#v, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal) } } } func TestWrappedTimstamp_MarshalReflexivity(t *testing.T) { testCases := []struct { desc string data WrappedTimestamp }{ {"Reference", WrappedTimestamp{0, Timestamp{referenceTime}}}, {"Empty", WrappedTimestamp{0, Timestamp{}}}, } for _, tc := range testCases { bytes, err := json.Marshal(tc.data) if err != nil { t.Errorf("%s: Marshal err=%v", tc.desc, err) } var got WrappedTimestamp err = json.Unmarshal(bytes, &got) if err != nil { t.Errorf("%s: Unmarshal err=%v", tc.desc, err) } if !got.Time.Equal(tc.data.Time) { t.Errorf("%s: %+v != %+v", tc.desc, got, tc.data) } } } go-github-28.1.1/github/users.go000066400000000000000000000222441353501270500164470ustar00rootroot00000000000000// 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" ) // UsersService handles communication with the user related // methods of the GitHub API. // // GitHub API docs: https://developer.github.com/v3/users/ type UsersService service // User represents a GitHub user. type User struct { Login *string `json:"login,omitempty"` ID *int64 `json:"id,omitempty"` NodeID *string `json:"node_id,omitempty"` AvatarURL *string `json:"avatar_url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` GravatarID *string `json:"gravatar_id,omitempty"` Name *string `json:"name,omitempty"` Company *string `json:"company,omitempty"` Blog *string `json:"blog,omitempty"` Location *string `json:"location,omitempty"` Email *string `json:"email,omitempty"` Hireable *bool `json:"hireable,omitempty"` Bio *string `json:"bio,omitempty"` PublicRepos *int `json:"public_repos,omitempty"` PublicGists *int `json:"public_gists,omitempty"` Followers *int `json:"followers,omitempty"` Following *int `json:"following,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` SuspendedAt *Timestamp `json:"suspended_at,omitempty"` Type *string `json:"type,omitempty"` SiteAdmin *bool `json:"site_admin,omitempty"` TotalPrivateRepos *int `json:"total_private_repos,omitempty"` OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"` PrivateGists *int `json:"private_gists,omitempty"` DiskUsage *int `json:"disk_usage,omitempty"` Collaborators *int `json:"collaborators,omitempty"` TwoFactorAuthentication *bool `json:"two_factor_authentication,omitempty"` Plan *Plan `json:"plan,omitempty"` LdapDn *string `json:"ldap_dn,omitempty"` // API URLs URL *string `json:"url,omitempty"` EventsURL *string `json:"events_url,omitempty"` FollowingURL *string `json:"following_url,omitempty"` FollowersURL *string `json:"followers_url,omitempty"` GistsURL *string `json:"gists_url,omitempty"` OrganizationsURL *string `json:"organizations_url,omitempty"` ReceivedEventsURL *string `json:"received_events_url,omitempty"` ReposURL *string `json:"repos_url,omitempty"` StarredURL *string `json:"starred_url,omitempty"` SubscriptionsURL *string `json:"subscriptions_url,omitempty"` // TextMatches is only populated from search results that request text matches // See: search.go and https://developer.github.com/v3/search/#text-match-metadata TextMatches []TextMatch `json:"text_matches,omitempty"` // Permissions identifies the permissions that a user has on a given // repository. This is only populated when calling Repositories.ListCollaborators. Permissions *map[string]bool `json:"permissions,omitempty"` } func (u User) String() string { return Stringify(u) } // Get fetches a user. Passing the empty string will fetch the authenticated // 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 func (s *UsersService) Get(ctx context.Context, user string) (*User, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v", user) } else { u = "user" } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } uResp := new(User) resp, err := s.client.Do(ctx, req, uResp) if err != nil { return nil, resp, err } return uResp, resp, nil } // GetByID fetches a user. // // Note: GetByID uses the undocumented GitHub API endpoint /user/:id. func (s *UsersService) GetByID(ctx context.Context, id int64) (*User, *Response, error) { u := fmt.Sprintf("user/%d", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } user := new(User) resp, err := s.client.Do(ctx, req, user) if err != nil { return nil, resp, err } return user, resp, nil } // Edit the authenticated user. // // GitHub API docs: https://developer.github.com/v3/users/#update-the-authenticated-user func (s *UsersService) Edit(ctx context.Context, user *User) (*User, *Response, error) { u := "user" req, err := s.client.NewRequest("PATCH", u, user) if err != nil { return nil, nil, err } uResp := new(User) resp, err := s.client.Do(ctx, req, uResp) if err != nil { return nil, resp, err } return uResp, resp, nil } // HovercardOptions specifies optional parameters to the UsersService.GetHovercard // method. type HovercardOptions struct { // SubjectType specifies the additional information to be received about the hovercard. // Possible values are: organization, repository, issue, pull_request. (Required when using subject_id.) SubjectType string `url:"subject_type"` // SubjectID specifies the ID for the SubjectType. (Required when using subject_type.) SubjectID string `url:"subject_id"` } // Hovercard represents hovercard information about a user. type Hovercard struct { Contexts []*UserContext `json:"contexts,omitempty"` } // UserContext represents the contextual information about user. type UserContext struct { Message *string `json:"message,omitempty"` Octicon *string `json:"octicon,omitempty"` } // GetHovercard fetches contextual information about user. It requires authentication // via Basic Auth or via OAuth with the repo scope. // // GitHub API docs: https://developer.github.com/v3/users/#get-contextual-information-about-a-user func (s *UsersService) GetHovercard(ctx context.Context, user string, opt *HovercardOptions) (*Hovercard, *Response, error) { u := fmt.Sprintf("users/%v/hovercard", user) u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeHovercardPreview) hc := new(Hovercard) resp, err := s.client.Do(ctx, req, hc) if err != nil { return nil, resp, err } return hc, resp, nil } // UserListOptions specifies optional parameters to the UsersService.ListAll // method. type UserListOptions struct { // ID of the last user seen Since int64 `url:"since,omitempty"` // Note: Pagination is powered exclusively by the Since parameter, // ListOptions.Page has no effect. // ListOptions.PerPage controls an undocumented GitHub API parameter. ListOptions } // ListAll lists all GitHub users. // // To paginate through all users, populate 'Since' with the ID of the last user. // // GitHub API docs: https://developer.github.com/v3/users/#get-all-users func (s *UsersService) ListAll(ctx context.Context, opt *UserListOptions) ([]*User, *Response, error) { u, err := addOptions("users", opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var users []*User resp, err := s.client.Do(ctx, req, &users) if err != nil { return nil, resp, err } return users, resp, nil } // ListInvitations lists all currently-open repository invitations for the // authenticated user. // // GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-a-users-repository-invitations func (s *UsersService) ListInvitations(ctx context.Context, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) { u, err := addOptions("user/repository_invitations", opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } invites := []*RepositoryInvitation{} resp, err := s.client.Do(ctx, req, &invites) if err != nil { return nil, resp, err } return invites, resp, nil } // AcceptInvitation accepts the currently-open repository invitation for the // authenticated user. // // GitHub API docs: https://developer.github.com/v3/repos/invitations/#accept-a-repository-invitation func (s *UsersService) AcceptInvitation(ctx context.Context, invitationID int64) (*Response, error) { u := fmt.Sprintf("user/repository_invitations/%v", invitationID) req, err := s.client.NewRequest("PATCH", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // DeclineInvitation declines the currently-open repository invitation for the // authenticated user. // // GitHub API docs: https://developer.github.com/v3/repos/invitations/#decline-a-repository-invitation func (s *UsersService) DeclineInvitation(ctx context.Context, invitationID int64) (*Response, error) { u := fmt.Sprintf("user/repository_invitations/%v", invitationID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/users_administration.go000066400000000000000000000042611353501270500215530ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" ) // PromoteSiteAdmin promotes a user to a site administrator of a GitHub Enterprise instance. // // GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#promote-an-ordinary-user-to-a-site-administrator func (s *UsersService) PromoteSiteAdmin(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("users/%v/site_admin", user) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // DemoteSiteAdmin demotes a user from site administrator of a GitHub Enterprise instance. // // GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#demote-a-site-administrator-to-an-ordinary-user func (s *UsersService) DemoteSiteAdmin(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("users/%v/site_admin", user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // UserSuspendOptions represents the reason a user is being suspended. type UserSuspendOptions struct { Reason *string `json:"reason,omitempty"` } // Suspend a user on a GitHub Enterprise instance. // // GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#suspend-a-user func (s *UsersService) Suspend(ctx context.Context, user string, opt *UserSuspendOptions) (*Response, error) { u := fmt.Sprintf("users/%v/suspended", user) req, err := s.client.NewRequest("PUT", u, opt) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // Unsuspend a user on a GitHub Enterprise instance. // // GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#unsuspend-a-user func (s *UsersService) Unsuspend(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("users/%v/suspended", user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/users_administration_test.go000066400000000000000000000047161353501270500226170ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "encoding/json" "net/http" "reflect" "testing" ) func TestUsersService_PromoteSiteAdmin(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/site_admin", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") w.WriteHeader(http.StatusNoContent) }) _, err := client.Users.PromoteSiteAdmin(context.Background(), "u") if err != nil { t.Errorf("Users.PromoteSiteAdmin returned error: %v", err) } } func TestUsersService_DemoteSiteAdmin(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/site_admin", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Users.DemoteSiteAdmin(context.Background(), "u") if err != nil { t.Errorf("Users.DemoteSiteAdmin returned error: %v", err) } } func TestUsersService_Suspend(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/suspended", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") w.WriteHeader(http.StatusNoContent) }) _, err := client.Users.Suspend(context.Background(), "u", nil) if err != nil { t.Errorf("Users.Suspend returned error: %v", err) } } func TestUsersServiceReason_Suspend(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &UserSuspendOptions{Reason: String("test")} mux.HandleFunc("/users/u/suspended", func(w http.ResponseWriter, r *http.Request) { v := new(UserSuspendOptions) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "PUT") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } w.WriteHeader(http.StatusNoContent) }) _, err := client.Users.Suspend(context.Background(), "u", input) if err != nil { t.Errorf("Users.Suspend returned error: %v", err) } } func TestUsersService_Unsuspend(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/suspended", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) _, err := client.Users.Unsuspend(context.Background(), "u") if err != nil { t.Errorf("Users.Unsuspend returned error: %v", err) } } go-github-28.1.1/github/users_blocking.go000066400000000000000000000051631353501270500203200ustar00rootroot00000000000000// Copyright 2017 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" ) // ListBlockedUsers lists all the blocked users by the authenticated user. // // GitHub API docs: https://developer.github.com/v3/users/blocking/#list-blocked-users func (s *UsersService) ListBlockedUsers(ctx context.Context, opt *ListOptions) ([]*User, *Response, error) { u := "user/blocks" u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeBlockUsersPreview) var blockedUsers []*User resp, err := s.client.Do(ctx, req, &blockedUsers) if err != nil { return nil, resp, err } return blockedUsers, resp, nil } // IsBlocked reports whether specified user is blocked by the authenticated user. // // GitHub API docs: https://developer.github.com/v3/users/blocking/#check-whether-youve-blocked-a-user func (s *UsersService) IsBlocked(ctx context.Context, user string) (bool, *Response, error) { u := fmt.Sprintf("user/blocks/%v", user) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeBlockUsersPreview) resp, err := s.client.Do(ctx, req, nil) isBlocked, err := parseBoolResponse(err) return isBlocked, resp, err } // BlockUser blocks specified user for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/users/blocking/#block-a-user func (s *UsersService) BlockUser(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("user/blocks/%v", user) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeBlockUsersPreview) return s.client.Do(ctx, req, nil) } // UnblockUser unblocks specified user for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/users/blocking/#unblock-a-user func (s *UsersService) UnblockUser(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("user/blocks/%v", user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } // TODO: remove custom Accept header when this API fully launches. req.Header.Set("Accept", mediaTypeBlockUsersPreview) return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/users_blocking_test.go000066400000000000000000000046441353501270500213620ustar00rootroot00000000000000// Copyright 2017 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" "reflect" "testing" ) func TestUsersService_ListBlockedUsers(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/blocks", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeBlockUsersPreview) testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{ "login": "octocat" }]`) }) opt := &ListOptions{Page: 2} blockedUsers, _, err := client.Users.ListBlockedUsers(context.Background(), opt) if err != nil { t.Errorf("Users.ListBlockedUsers returned error: %v", err) } want := []*User{{Login: String("octocat")}} if !reflect.DeepEqual(blockedUsers, want) { t.Errorf("Users.ListBlockedUsers returned %+v, want %+v", blockedUsers, want) } } func TestUsersService_IsBlocked(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/blocks/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeBlockUsersPreview) w.WriteHeader(http.StatusNoContent) }) isBlocked, _, err := client.Users.IsBlocked(context.Background(), "u") if err != nil { t.Errorf("Users.IsBlocked returned error: %v", err) } if want := true; isBlocked != want { t.Errorf("Users.IsBlocked returned %+v, want %+v", isBlocked, want) } } func TestUsersService_BlockUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/blocks/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testHeader(t, r, "Accept", mediaTypeBlockUsersPreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Users.BlockUser(context.Background(), "u") if err != nil { t.Errorf("Users.BlockUser returned error: %v", err) } } func TestUsersService_UnblockUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/blocks/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testHeader(t, r, "Accept", mediaTypeBlockUsersPreview) w.WriteHeader(http.StatusNoContent) }) _, err := client.Users.UnblockUser(context.Background(), "u") if err != nil { t.Errorf("Users.UnblockUser returned error: %v", err) } } go-github-28.1.1/github/users_emails.go000066400000000000000000000036701353501270500200030ustar00rootroot00000000000000// 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" // UserEmail represents user's email address type UserEmail struct { Email *string `json:"email,omitempty"` Primary *bool `json:"primary,omitempty"` Verified *bool `json:"verified,omitempty"` Visibility *string `json:"visibility,omitempty"` } // ListEmails lists all email addresses for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user func (s *UsersService) ListEmails(ctx context.Context, opt *ListOptions) ([]*UserEmail, *Response, error) { u := "user/emails" u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var emails []*UserEmail resp, err := s.client.Do(ctx, req, &emails) if err != nil { return nil, resp, err } return emails, resp, nil } // AddEmails adds email addresses of the authenticated user. // // GitHub API docs: https://developer.github.com/v3/users/emails/#add-email-addresses func (s *UsersService) AddEmails(ctx context.Context, emails []string) ([]*UserEmail, *Response, error) { u := "user/emails" req, err := s.client.NewRequest("POST", u, emails) if err != nil { return nil, nil, err } var e []*UserEmail resp, err := s.client.Do(ctx, req, &e) if err != nil { return nil, resp, err } return e, resp, nil } // DeleteEmails deletes email addresses from authenticated user. // // GitHub API docs: https://developer.github.com/v3/users/emails/#delete-email-addresses func (s *UsersService) DeleteEmails(ctx context.Context, emails []string) (*Response, error) { u := "user/emails" req, err := s.client.NewRequest("DELETE", u, emails) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/users_emails_test.go000066400000000000000000000045561353501270500210460ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestUsersService_ListEmails(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/emails", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{ "email": "user@example.com", "verified": false, "primary": true }]`) }) opt := &ListOptions{Page: 2} emails, _, err := client.Users.ListEmails(context.Background(), opt) if err != nil { t.Errorf("Users.ListEmails returned error: %v", err) } want := []*UserEmail{{Email: String("user@example.com"), Verified: Bool(false), Primary: Bool(true)}} if !reflect.DeepEqual(emails, want) { t.Errorf("Users.ListEmails returned %+v, want %+v", emails, want) } } func TestUsersService_AddEmails(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := []string{"new@example.com"} mux.HandleFunc("/user/emails", func(w http.ResponseWriter, r *http.Request) { var v []string json.NewDecoder(r.Body).Decode(&v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `[{"email":"old@example.com"}, {"email":"new@example.com"}]`) }) emails, _, err := client.Users.AddEmails(context.Background(), input) if err != nil { t.Errorf("Users.AddEmails returned error: %v", err) } want := []*UserEmail{ {Email: String("old@example.com")}, {Email: String("new@example.com")}, } if !reflect.DeepEqual(emails, want) { t.Errorf("Users.AddEmails returned %+v, want %+v", emails, want) } } func TestUsersService_DeleteEmails(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := []string{"user@example.com"} mux.HandleFunc("/user/emails", func(w http.ResponseWriter, r *http.Request) { var v []string json.NewDecoder(r.Body).Decode(&v) testMethod(t, r, "DELETE") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } }) _, err := client.Users.DeleteEmails(context.Background(), input) if err != nil { t.Errorf("Users.DeleteEmails returned error: %v", err) } } go-github-28.1.1/github/users_followers.go000066400000000000000000000063671353501270500205530ustar00rootroot00000000000000// 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" ) // 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 func (s *UsersService) ListFollowers(ctx context.Context, user string, opt *ListOptions) ([]*User, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/followers", user) } else { u = "user/followers" } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var users []*User resp, err := s.client.Do(ctx, req, &users) if err != nil { return nil, resp, err } return users, resp, nil } // 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 func (s *UsersService) ListFollowing(ctx context.Context, user string, opt *ListOptions) ([]*User, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/following", user) } else { u = "user/following" } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var users []*User resp, err := s.client.Do(ctx, req, &users) if err != nil { return nil, resp, err } return users, resp, nil } // 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 func (s *UsersService) IsFollowing(ctx context.Context, user, target string) (bool, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/following/%v", user, target) } else { u = fmt.Sprintf("user/following/%v", target) } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } resp, err := s.client.Do(ctx, req, nil) following, err := parseBoolResponse(err) return following, resp, err } // Follow will cause the authenticated user to follow the specified user. // // GitHub API docs: https://developer.github.com/v3/users/followers/#follow-a-user func (s *UsersService) Follow(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("user/following/%v", user) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } // Unfollow will cause the authenticated user to unfollow the specified user. // // GitHub API docs: https://developer.github.com/v3/users/followers/#unfollow-a-user func (s *UsersService) Unfollow(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("user/following/%v", user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/users_followers_test.go000066400000000000000000000147341353501270500216070ustar00rootroot00000000000000// 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" "net/http" "reflect" "testing" ) func TestUsersService_ListFollowers_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/followers", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} users, _, err := client.Users.ListFollowers(context.Background(), "", opt) if err != nil { t.Errorf("Users.ListFollowers returned error: %v", err) } want := []*User{{ID: Int64(1)}} if !reflect.DeepEqual(users, want) { t.Errorf("Users.ListFollowers returned %+v, want %+v", users, want) } } func TestUsersService_ListFollowers_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/followers", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1}]`) }) users, _, err := client.Users.ListFollowers(context.Background(), "u", nil) if err != nil { t.Errorf("Users.ListFollowers returned error: %v", err) } want := []*User{{ID: Int64(1)}} if !reflect.DeepEqual(users, want) { t.Errorf("Users.ListFollowers returned %+v, want %+v", users, want) } } func TestUsersService_ListFollowers_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Users.ListFollowers(context.Background(), "%", nil) testURLParseError(t, err) } func TestUsersService_ListFollowing_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/following", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opts := &ListOptions{Page: 2} users, _, err := client.Users.ListFollowing(context.Background(), "", opts) if err != nil { t.Errorf("Users.ListFollowing returned error: %v", err) } want := []*User{{ID: Int64(1)}} if !reflect.DeepEqual(users, want) { t.Errorf("Users.ListFollowing returned %+v, want %+v", users, want) } } func TestUsersService_ListFollowing_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/following", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1}]`) }) users, _, err := client.Users.ListFollowing(context.Background(), "u", nil) if err != nil { t.Errorf("Users.ListFollowing returned error: %v", err) } want := []*User{{ID: Int64(1)}} if !reflect.DeepEqual(users, want) { t.Errorf("Users.ListFollowing returned %+v, want %+v", users, want) } } func TestUsersService_ListFollowing_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Users.ListFollowing(context.Background(), "%", nil) testURLParseError(t, err) } func TestUsersService_IsFollowing_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/following/t", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNoContent) }) following, _, err := client.Users.IsFollowing(context.Background(), "", "t") if err != nil { t.Errorf("Users.IsFollowing returned error: %v", err) } if want := true; following != want { t.Errorf("Users.IsFollowing returned %+v, want %+v", following, want) } } func TestUsersService_IsFollowing_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/following/t", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNoContent) }) following, _, err := client.Users.IsFollowing(context.Background(), "u", "t") if err != nil { t.Errorf("Users.IsFollowing returned error: %v", err) } if want := true; following != want { t.Errorf("Users.IsFollowing returned %+v, want %+v", following, want) } } func TestUsersService_IsFollowing_false(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/following/t", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) }) following, _, err := client.Users.IsFollowing(context.Background(), "u", "t") if err != nil { t.Errorf("Users.IsFollowing returned error: %v", err) } if want := false; following != want { t.Errorf("Users.IsFollowing returned %+v, want %+v", following, want) } } func TestUsersService_IsFollowing_error(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/following/t", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") http.Error(w, "BadRequest", http.StatusBadRequest) }) following, _, err := client.Users.IsFollowing(context.Background(), "u", "t") if err == nil { t.Errorf("Expected HTTP 400 response") } if want := false; following != want { t.Errorf("Users.IsFollowing returned %+v, want %+v", following, want) } } func TestUsersService_IsFollowing_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Users.IsFollowing(context.Background(), "%", "%") testURLParseError(t, err) } func TestUsersService_Follow(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/following/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") }) _, err := client.Users.Follow(context.Background(), "u") if err != nil { t.Errorf("Users.Follow returned error: %v", err) } } func TestUsersService_Follow_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Users.Follow(context.Background(), "%") testURLParseError(t, err) } func TestUsersService_Unfollow(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/following/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Users.Unfollow(context.Background(), "u") if err != nil { t.Errorf("Users.Follow returned error: %v", err) } } func TestUsersService_Unfollow_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, err := client.Users.Unfollow(context.Background(), "%") testURLParseError(t, err) } go-github-28.1.1/github/users_gpg_keys.go000066400000000000000000000076511353501270500203440ustar00rootroot00000000000000// Copyright 2016 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "time" ) // GPGKey represents a GitHub user's public GPG key used to verify GPG signed commits and tags. // // https://developer.github.com/changes/2016-04-04-git-signing-api-preview/ type GPGKey struct { ID *int64 `json:"id,omitempty"` PrimaryKeyID *int64 `json:"primary_key_id,omitempty"` KeyID *string `json:"key_id,omitempty"` PublicKey *string `json:"public_key,omitempty"` Emails []GPGEmail `json:"emails,omitempty"` Subkeys []GPGKey `json:"subkeys,omitempty"` CanSign *bool `json:"can_sign,omitempty"` CanEncryptComms *bool `json:"can_encrypt_comms,omitempty"` CanEncryptStorage *bool `json:"can_encrypt_storage,omitempty"` CanCertify *bool `json:"can_certify,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` ExpiresAt *time.Time `json:"expires_at,omitempty"` } // String stringifies a GPGKey. func (k GPGKey) String() string { return Stringify(k) } // GPGEmail represents an email address associated to a GPG key. type GPGEmail struct { Email *string `json:"email,omitempty"` Verified *bool `json:"verified,omitempty"` } // ListGPGKeys lists the public GPG keys for a user. Passing the empty // 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 func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opt *ListOptions) ([]*GPGKey, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/gpg_keys", user) } else { u = "user/gpg_keys" } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var keys []*GPGKey resp, err := s.client.Do(ctx, req, &keys) if err != nil { return nil, resp, err } return keys, resp, nil } // GetGPGKey gets extended details for a single GPG key. 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/#get-a-single-gpg-key func (s *UsersService) GetGPGKey(ctx context.Context, id int64) (*GPGKey, *Response, error) { u := fmt.Sprintf("user/gpg_keys/%v", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } key := &GPGKey{} resp, err := s.client.Do(ctx, req, key) if err != nil { return nil, resp, err } return key, resp, nil } // CreateGPGKey creates a GPG key. It requires authenticatation via Basic Auth // or OAuth with at least write:gpg_key scope. // // GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#create-a-gpg-key func (s *UsersService) CreateGPGKey(ctx context.Context, armoredPublicKey string) (*GPGKey, *Response, error) { gpgKey := &struct { ArmoredPublicKey string `json:"armored_public_key"` }{ArmoredPublicKey: armoredPublicKey} req, err := s.client.NewRequest("POST", "user/gpg_keys", gpgKey) if err != nil { return nil, nil, err } key := &GPGKey{} resp, err := s.client.Do(ctx, req, key) if err != nil { return nil, resp, err } return key, resp, nil } // DeleteGPGKey deletes a GPG key. It requires authentication via Basic Auth or // via OAuth with at least admin:gpg_key scope. // // GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#delete-a-gpg-key func (s *UsersService) DeleteGPGKey(ctx context.Context, id int64) (*Response, error) { u := fmt.Sprintf("user/gpg_keys/%v", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/users_gpg_keys_test.go000066400000000000000000000070631353501270500214000ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestUsersService_ListGPGKeys_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/gpg_keys", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1,"primary_key_id":2}]`) }) opt := &ListOptions{Page: 2} keys, _, err := client.Users.ListGPGKeys(context.Background(), "", opt) if err != nil { t.Errorf("Users.ListGPGKeys returned error: %v", err) } want := []*GPGKey{{ID: Int64(1), PrimaryKeyID: Int64(2)}} if !reflect.DeepEqual(keys, want) { t.Errorf("Users.ListGPGKeys = %+v, want %+v", keys, want) } } func TestUsersService_ListGPGKeys_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/gpg_keys", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1,"primary_key_id":2}]`) }) keys, _, err := client.Users.ListGPGKeys(context.Background(), "u", nil) if err != nil { t.Errorf("Users.ListGPGKeys returned error: %v", err) } want := []*GPGKey{{ID: Int64(1), PrimaryKeyID: Int64(2)}} if !reflect.DeepEqual(keys, want) { t.Errorf("Users.ListGPGKeys = %+v, want %+v", keys, want) } } func TestUsersService_ListGPGKeys_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Users.ListGPGKeys(context.Background(), "%", nil) testURLParseError(t, err) } func TestUsersService_GetGPGKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/gpg_keys/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) key, _, err := client.Users.GetGPGKey(context.Background(), 1) if err != nil { t.Errorf("Users.GetGPGKey returned error: %v", err) } want := &GPGKey{ID: Int64(1)} if !reflect.DeepEqual(key, want) { t.Errorf("Users.GetGPGKey = %+v, want %+v", key, want) } } func TestUsersService_CreateGPGKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := ` -----BEGIN PGP PUBLIC KEY BLOCK----- Comment: GPGTools - https://gpgtools.org mQINBFcEd9kBEACo54TDbGhKlXKWMvJgecEUKPPcv7XdnpKdGb3LRw5MvFwT0V0f ... =tqfb -----END PGP PUBLIC KEY BLOCK-----` mux.HandleFunc("/user/gpg_keys", func(w http.ResponseWriter, r *http.Request) { var gpgKey struct { ArmoredPublicKey *string `json:"armored_public_key,omitempty"` } json.NewDecoder(r.Body).Decode(&gpgKey) testMethod(t, r, "POST") if gpgKey.ArmoredPublicKey == nil || *gpgKey.ArmoredPublicKey != input { t.Errorf("gpgKey = %+v, want %q", gpgKey, input) } fmt.Fprint(w, `{"id":1}`) }) gpgKey, _, err := client.Users.CreateGPGKey(context.Background(), input) if err != nil { t.Errorf("Users.GetGPGKey returned error: %v", err) } want := &GPGKey{ID: Int64(1)} if !reflect.DeepEqual(gpgKey, want) { t.Errorf("Users.GetGPGKey = %+v, want %+v", gpgKey, want) } } func TestUsersService_DeleteGPGKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/gpg_keys/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Users.DeleteGPGKey(context.Background(), 1) if err != nil { t.Errorf("Users.DeleteGPGKey returned error: %v", err) } } go-github-28.1.1/github/users_keys.go000066400000000000000000000052341353501270500175020ustar00rootroot00000000000000// 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" ) // Key represents a public SSH key used to authenticate a user or deploy script. type Key struct { ID *int64 `json:"id,omitempty"` Key *string `json:"key,omitempty"` URL *string `json:"url,omitempty"` Title *string `json:"title,omitempty"` ReadOnly *bool `json:"read_only,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` } func (k Key) String() string { return Stringify(k) } // 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 func (s *UsersService) ListKeys(ctx context.Context, user string, opt *ListOptions) ([]*Key, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/keys", user) } else { u = "user/keys" } u, err := addOptions(u, opt) if err != nil { return nil, nil, err } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } var keys []*Key resp, err := s.client.Do(ctx, req, &keys) if err != nil { return nil, resp, err } return keys, resp, nil } // GetKey fetches a single public key. // // GitHub API docs: https://developer.github.com/v3/users/keys/#get-a-single-public-key func (s *UsersService) GetKey(ctx context.Context, id int64) (*Key, *Response, error) { u := fmt.Sprintf("user/keys/%v", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } key := new(Key) resp, err := s.client.Do(ctx, req, key) if err != nil { return nil, resp, err } return key, resp, nil } // CreateKey adds a public key for the authenticated user. // // GitHub API docs: https://developer.github.com/v3/users/keys/#create-a-public-key func (s *UsersService) CreateKey(ctx context.Context, key *Key) (*Key, *Response, error) { u := "user/keys" req, err := s.client.NewRequest("POST", 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 public key. // // GitHub API docs: https://developer.github.com/v3/users/keys/#delete-a-public-key func (s *UsersService) DeleteKey(ctx context.Context, id int64) (*Response, error) { u := fmt.Sprintf("user/keys/%v", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } return s.client.Do(ctx, req, nil) } go-github-28.1.1/github/users_keys_test.go000066400000000000000000000062051353501270500205400ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestUsersService_ListKeys_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/keys", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `[{"id":1}]`) }) opt := &ListOptions{Page: 2} keys, _, err := client.Users.ListKeys(context.Background(), "", opt) if err != nil { t.Errorf("Users.ListKeys returned error: %v", err) } want := []*Key{{ID: Int64(1)}} if !reflect.DeepEqual(keys, want) { t.Errorf("Users.ListKeys returned %+v, want %+v", keys, want) } } func TestUsersService_ListKeys_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/keys", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{"id":1}]`) }) keys, _, err := client.Users.ListKeys(context.Background(), "u", nil) if err != nil { t.Errorf("Users.ListKeys returned error: %v", err) } want := []*Key{{ID: Int64(1)}} if !reflect.DeepEqual(keys, want) { t.Errorf("Users.ListKeys returned %+v, want %+v", keys, want) } } func TestUsersService_ListKeys_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Users.ListKeys(context.Background(), "%", nil) testURLParseError(t, err) } func TestUsersService_GetKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/keys/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) key, _, err := client.Users.GetKey(context.Background(), 1) if err != nil { t.Errorf("Users.GetKey returned error: %v", err) } want := &Key{ID: Int64(1)} if !reflect.DeepEqual(key, want) { t.Errorf("Users.GetKey returned %+v, want %+v", key, want) } } func TestUsersService_CreateKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &Key{Key: String("k"), Title: String("t")} mux.HandleFunc("/user/keys", func(w http.ResponseWriter, r *http.Request) { v := new(Key) json.NewDecoder(r.Body).Decode(v) testMethod(t, r, "POST") if !reflect.DeepEqual(v, input) { t.Errorf("Request body = %+v, want %+v", v, input) } fmt.Fprint(w, `{"id":1}`) }) key, _, err := client.Users.CreateKey(context.Background(), input) if err != nil { t.Errorf("Users.GetKey returned error: %v", err) } want := &Key{ID: Int64(1)} if !reflect.DeepEqual(key, want) { t.Errorf("Users.GetKey returned %+v, want %+v", key, want) } } func TestUsersService_DeleteKey(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/keys/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) _, err := client.Users.DeleteKey(context.Background(), 1) if err != nil { t.Errorf("Users.DeleteKey returned error: %v", err) } } go-github-28.1.1/github/users_test.go000066400000000000000000000157031353501270500175100ustar00rootroot00000000000000// 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" "encoding/json" "fmt" "net/http" "reflect" "testing" ) func TestUser_marshall(t *testing.T) { testJSONMarshal(t, &User{}, "{}") u := &User{ Login: String("l"), ID: Int64(1), URL: String("u"), AvatarURL: String("a"), GravatarID: String("g"), Name: String("n"), Company: String("c"), Blog: String("b"), Location: String("l"), Email: String("e"), Hireable: Bool(true), PublicRepos: Int(1), Followers: Int(1), Following: Int(1), CreatedAt: &Timestamp{referenceTime}, SuspendedAt: &Timestamp{referenceTime}, } want := `{ "login": "l", "id": 1, "avatar_url": "a", "gravatar_id": "g", "name": "n", "company": "c", "blog": "b", "location": "l", "email": "e", "hireable": true, "public_repos": 1, "followers": 1, "following": 1, "created_at": ` + referenceTimeStr + `, "suspended_at": ` + referenceTimeStr + `, "url": "u" }` testJSONMarshal(t, u, want) } func TestUsersService_Get_authenticatedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) user, _, err := client.Users.Get(context.Background(), "") if err != nil { t.Errorf("Users.Get returned error: %v", err) } want := &User{ID: Int64(1)} if !reflect.DeepEqual(user, want) { t.Errorf("Users.Get returned %+v, want %+v", user, want) } } func TestUsersService_Get_specifiedUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) user, _, err := client.Users.Get(context.Background(), "u") if err != nil { t.Errorf("Users.Get returned error: %v", err) } want := &User{ID: Int64(1)} if !reflect.DeepEqual(user, want) { t.Errorf("Users.Get returned %+v, want %+v", user, want) } } func TestUsersService_Get_invalidUser(t *testing.T) { client, _, _, teardown := setup() defer teardown() _, _, err := client.Users.Get(context.Background(), "%") testURLParseError(t, err) } func TestUsersService_GetByID(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{"id":1}`) }) user, _, err := client.Users.GetByID(context.Background(), 1) if err != nil { t.Fatalf("Users.GetByID returned error: %v", err) } want := &User{ID: Int64(1)} if !reflect.DeepEqual(user, want) { t.Errorf("Users.GetByID returned %+v, want %+v", user, want) } } func TestUsersService_Edit(t *testing.T) { client, mux, _, teardown := setup() defer teardown() input := &User{Name: String("n")} mux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { v := new(User) 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}`) }) user, _, err := client.Users.Edit(context.Background(), input) if err != nil { t.Errorf("Users.Edit returned error: %v", err) } want := &User{ID: Int64(1)} if !reflect.DeepEqual(user, want) { t.Errorf("Users.Edit returned %+v, want %+v", user, want) } } func TestUsersService_GetHovercard(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users/u/hovercard", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testHeader(t, r, "Accept", mediaTypeHovercardPreview) testFormValues(t, r, values{"subject_type": "repository", "subject_id": "20180408"}) fmt.Fprint(w, `{"contexts": [{"message":"Owns this repository", "octicon": "repo"}]}`) }) opt := &HovercardOptions{SubjectType: "repository", SubjectID: "20180408"} hovercard, _, err := client.Users.GetHovercard(context.Background(), "u", opt) if err != nil { t.Errorf("Users.GetHovercard returned error: %v", err) } want := &Hovercard{Contexts: []*UserContext{{Message: String("Owns this repository"), Octicon: String("repo")}}} if !reflect.DeepEqual(hovercard, want) { t.Errorf("Users.GetHovercard returned %+v, want %+v", hovercard, want) } } func TestUsersService_ListAll(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"since": "1", "page": "2"}) fmt.Fprint(w, `[{"id":2}]`) }) opt := &UserListOptions{1, ListOptions{Page: 2}} users, _, err := client.Users.ListAll(context.Background(), opt) if err != nil { t.Errorf("Users.Get returned error: %v", err) } want := []*User{{ID: Int64(2)}} if !reflect.DeepEqual(users, want) { t.Errorf("Users.ListAll returned %+v, want %+v", users, want) } } func TestUsersService_ListInvitations(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/repository_invitations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprintf(w, `[{"id":1}, {"id":2}]`) }) got, _, err := client.Users.ListInvitations(context.Background(), nil) if err != nil { t.Errorf("Users.ListInvitations returned error: %v", err) } want := []*RepositoryInvitation{{ID: Int64(1)}, {ID: Int64(2)}} if !reflect.DeepEqual(got, want) { t.Errorf("Users.ListInvitations = %+v, want %+v", got, want) } } func TestUsersService_ListInvitations_withOptions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/repository_invitations", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", }) fmt.Fprintf(w, `[{"id":1}, {"id":2}]`) }) _, _, err := client.Users.ListInvitations(context.Background(), &ListOptions{Page: 2}) if err != nil { t.Errorf("Users.ListInvitations returned error: %v", err) } } func TestUsersService_AcceptInvitation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/repository_invitations/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") w.WriteHeader(http.StatusNoContent) }) if _, err := client.Users.AcceptInvitation(context.Background(), 1); err != nil { t.Errorf("Users.AcceptInvitation returned error: %v", err) } } func TestUsersService_DeclineInvitation(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/user/repository_invitations/1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) if _, err := client.Users.DeclineInvitation(context.Background(), 1); err != nil { t.Errorf("Users.DeclineInvitation returned error: %v", err) } } go-github-28.1.1/github/with_appengine.go000066400000000000000000000007171353501270500203100ustar00rootroot00000000000000// Copyright 2017 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 appengine // This file provides glue for making github work on App Engine. package github import ( "context" "net/http" ) func withContext(ctx context.Context, req *http.Request) *http.Request { // No-op because App Engine adds context to a request differently. return req } go-github-28.1.1/github/without_appengine.go000066400000000000000000000006421353501270500210350ustar00rootroot00000000000000// Copyright 2017 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 !appengine // This file provides glue for making github work without App Engine. package github import ( "context" "net/http" ) func withContext(ctx context.Context, req *http.Request) *http.Request { return req.WithContext(ctx) } go-github-28.1.1/go.mod000066400000000000000000000006541353501270500146040ustar00rootroot00000000000000module github.com/google/go-github/v28 require ( github.com/golang/protobuf v1.2.0 // indirect github.com/google/go-querystring v1.0.0 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 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 // indirect google.golang.org/appengine v1.1.0 ) go 1.13 go-github-28.1.1/go.sum000066400000000000000000000031701353501270500146250ustar00rootroot00000000000000github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/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= 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= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= go-github-28.1.1/test/000077500000000000000000000000001353501270500144505ustar00rootroot00000000000000go-github-28.1.1/test/README.md000066400000000000000000000052341353501270500157330ustar00rootroot00000000000000go-github tests =============== This directory contains additional test suites beyond the unit tests already in [../github](../github). Whereas the unit tests run very quickly (since they don't make any network calls) and are run by Travis on every commit, the tests in this directory are only run manually. The test packages are: integration ----------- This will exercise the entire go-github library (or at least as much as is practical) against the live GitHub API. These tests will verify that the library is properly coded against the actual behavior of the API, and will (hopefully) fail upon any incompatible change in the API. Because these tests are running using live data, there is a much higher probability of false positives in test failures due to network issues, test data having been changed, etc. These tests send real network traffic to the GitHub API and will exhaust the default unregistered rate limit (60 requests per hour) very quickly. Additionally, in order to test the methods that modify data, a real OAuth token will need to be present. While the tests will try to be well-behaved in terms of what data they modify, it is **strongly** recommended that these tests only be run using a dedicated test account. Run tests using: GITHUB_AUTH_TOKEN=XXX go test -v -tags=integration ./integration Additionally there are a set of integration tests for the Authorizations API. These tests require a GitHub user (username and password), and also that a [GitHub Application](https://github.com/settings/applications/new) (with attendant Client ID and Client Secret) be available. Then, to execute just the Authorization tests: GITHUB_USERNAME='' GITHUB_PASSWORD='' GITHUB_CLIENT_ID='' GITHUB_CLIENT_SECRET='' go test -v -tags=integration -run=Authorizations ./integration If some or all of these environment variables are not available, certain of the Authorization integration tests will be skipped. fields ------ This will identify the fields being returned by the live GitHub API that are not currently being mapped into the relevant Go data type. Sometimes fields are deliberately not mapped, so the results of this tool should just be taken as a hint. This test sends real network traffic to the GitHub API and will exhaust the default unregistered rate limit (60 requests per hour) very quickly. Additionally, some data is only returned for authenticated API calls. Unlike the integration tests above, these tests only read data, so it's less imperative that these be run using a dedicated test account (though you still really should). Run the fields tool using: GITHUB_AUTH_TOKEN=XXX go run ./fields/fields.go go-github-28.1.1/test/fields/000077500000000000000000000000001353501270500157165ustar00rootroot00000000000000go-github-28.1.1/test/fields/fields.go000066400000000000000000000071601353501270500175170ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // This tool tests for the JSON mappings in the go-github data types. It will // identify fields that are returned by the live GitHub API, but that are not // currently mapped into a struct field of the relevant go-github type. This // helps to ensure that all relevant data returned by the API is being made // accessible, particularly new fields that are periodically (and sometimes // quietly) added to the API over time. // // These tests simply aid in identifying which fields aren't being mapped; it // is not necessarily true that every one of them should always be mapped. // Some fields may be undocumented for a reason, either because they aren't // actually used yet or should not be relied upon. package main import ( "context" "encoding/json" "flag" "fmt" "os" "reflect" "strings" "github.com/google/go-github/v28/github" "golang.org/x/oauth2" ) var ( client *github.Client // auth indicates whether tests are being run with an OAuth token. // Tests can use this flag to skip certain tests when run without auth. auth bool skipURLs = flag.Bool("skip_urls", false, "skip url fields") ) func main() { flag.Parse() token := os.Getenv("GITHUB_AUTH_TOKEN") if token == "" { print("!!! No OAuth token. Some tests won't run. !!!\n\n") client = github.NewClient(nil) } else { tc := oauth2.NewClient(context.Background(), oauth2.StaticTokenSource( &oauth2.Token{AccessToken: token}, )) client = github.NewClient(tc) auth = true } for _, tt := range []struct { url string typ interface{} }{ //{"rate_limit", &github.RateLimits{}}, {"users/octocat", &github.User{}}, {"user", &github.User{}}, {"users/willnorris/keys", &[]github.Key{}}, {"orgs/google-test", &github.Organization{}}, {"repos/google/go-github", &github.Repository{}}, {"repos/google/go-github/issues/1", &github.Issue{}}, {"/gists/9257657", &github.Gist{}}, } { err := testType(tt.url, tt.typ) if err != nil { fmt.Printf("error: %v\n", err) } } } // testType fetches the JSON resource at urlStr and compares its keys to the // struct fields of typ. func testType(urlStr string, typ interface{}) error { slice := reflect.Indirect(reflect.ValueOf(typ)).Kind() == reflect.Slice req, err := client.NewRequest("GET", urlStr, nil) if err != nil { return err } // start with a json.RawMessage so we can decode multiple ways below raw := new(json.RawMessage) _, err = client.Do(context.Background(), req, raw) if err != nil { return err } // unmarshal directly to a map var m1 map[string]interface{} if slice { var s []map[string]interface{} err = json.Unmarshal(*raw, &s) if err != nil { return err } m1 = s[0] } else { err = json.Unmarshal(*raw, &m1) if err != nil { return err } } // unmarshal to typ first, then re-marshal and unmarshal to a map err = json.Unmarshal(*raw, typ) if err != nil { return err } var byt []byte if slice { // use first item in slice v := reflect.Indirect(reflect.ValueOf(typ)) byt, err = json.Marshal(v.Index(0).Interface()) if err != nil { return err } } else { byt, err = json.Marshal(typ) if err != nil { return err } } var m2 map[string]interface{} err = json.Unmarshal(byt, &m2) if err != nil { return err } // now compare the two maps for k, v := range m1 { if *skipURLs && strings.HasSuffix(k, "_url") { continue } if _, ok := m2[k]; !ok { fmt.Printf("%v missing field for key: %v (example value: %v)\n", reflect.TypeOf(typ), k, v) } } return nil } go-github-28.1.1/test/integration/000077500000000000000000000000001353501270500167735ustar00rootroot00000000000000go-github-28.1.1/test/integration/activity_test.go000066400000000000000000000100241353501270500222120ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build integration package integration import ( "context" "testing" "github.com/google/go-github/v28/github" ) const ( owner = "google" repo = "go-github" ) func TestActivity_Starring(t *testing.T) { stargazers, _, err := client.Activity.ListStargazers(context.Background(), owner, repo, nil) if err != nil { t.Fatalf("Activity.ListStargazers returned error: %v", err) } if len(stargazers) == 0 { t.Errorf("Activity.ListStargazers(%q, %q) returned no stargazers", owner, repo) } // the rest of the tests requires auth if !checkAuth("TestActivity_Starring") { return } // first, check if already starred the target repository star, _, err := client.Activity.IsStarred(context.Background(), owner, repo) if err != nil { t.Fatalf("Activity.IsStarred returned error: %v", err) } if star { t.Fatalf("Already starring %v/%v. Please manually unstar it first.", owner, repo) } // star the target repository _, err = client.Activity.Star(context.Background(), owner, repo) if err != nil { t.Fatalf("Activity.Star returned error: %v", err) } // check again and verify starred star, _, err = client.Activity.IsStarred(context.Background(), owner, repo) if err != nil { t.Fatalf("Activity.IsStarred returned error: %v", err) } if !star { t.Fatalf("Not starred %v/%v after starring it.", owner, repo) } // unstar _, err = client.Activity.Unstar(context.Background(), owner, repo) if err != nil { t.Fatalf("Activity.Unstar returned error: %v", err) } // check again and verify not watching star, _, err = client.Activity.IsStarred(context.Background(), owner, repo) if err != nil { t.Fatalf("Activity.IsStarred returned error: %v", err) } if star { t.Fatalf("Still starred %v/%v after unstarring it.", owner, repo) } } func deleteSubscription(t *testing.T) { // delete subscription _, err := client.Activity.DeleteRepositorySubscription(context.Background(), owner, repo) if err != nil { t.Fatalf("Activity.DeleteRepositorySubscription returned error: %v", err) } // check again and verify not watching sub, _, err := client.Activity.GetRepositorySubscription(context.Background(), owner, repo) if err != nil { t.Fatalf("Activity.GetRepositorySubscription returned error: %v", err) } if sub != nil { t.Fatalf("Still watching %v/%v after deleting subscription.", owner, repo) } } func createSubscription(t *testing.T) { // watch the target repository sub := &github.Subscription{Subscribed: github.Bool(true)} _, _, err := client.Activity.SetRepositorySubscription(context.Background(), owner, repo, sub) if err != nil { t.Fatalf("Activity.SetRepositorySubscription returned error: %v", err) } // check again and verify watching sub, _, err = client.Activity.GetRepositorySubscription(context.Background(), owner, repo) if err != nil { t.Fatalf("Activity.GetRepositorySubscription returned error: %v", err) } if sub == nil || !*sub.Subscribed { t.Fatalf("Not watching %v/%v after setting subscription.", owner, repo) } } func TestActivity_Watching(t *testing.T) { watchers, _, err := client.Activity.ListWatchers(context.Background(), owner, repo, nil) if err != nil { t.Fatalf("Activity.ListWatchers returned error: %v", err) } if len(watchers) == 0 { t.Errorf("Activity.ListWatchers(%q, %q) returned no watchers", owner, repo) } // the rest of the tests requires auth if !checkAuth("TestActivity_Watching") { return } // first, check if already watching the target repository sub, _, err := client.Activity.GetRepositorySubscription(context.Background(), owner, repo) if err != nil { t.Fatalf("Activity.GetRepositorySubscription returned error: %v", err) } switch { case sub != nil: // If already subscribing, delete then recreate subscription. deleteSubscription(t) createSubscription(t) case sub == nil: // Otherwise, create subscription and then delete it. createSubscription(t) deleteSubscription(t) } } go-github-28.1.1/test/integration/authorizations_test.go000066400000000000000000000245341353501270500234540ustar00rootroot00000000000000// 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. // +build integration package integration import ( "context" "math/rand" "os" "strconv" "strings" "testing" "time" "github.com/google/go-github/v28/github" ) const msgEnvMissing = "Skipping test because the required environment variable (%v) is not present." const envKeyGitHubUsername = "GITHUB_USERNAME" const envKeyGitHubPassword = "GITHUB_PASSWORD" const envKeyClientID = "GITHUB_CLIENT_ID" const envKeyClientSecret = "GITHUB_CLIENT_SECRET" const InvalidTokenValue = "iamnotacroken" // TestAuthorizationsBasicOperations tests the basic CRUD operations of the API (mostly for // the Personal Access Token scenario). func TestAuthorizationsBasicOperations(t *testing.T) { client := getUserPassClient(t) auths, resp, err := client.Authorizations.List(context.Background(), nil) failOnError(t, err) failIfNotStatusCode(t, resp, 200) initialAuthCount := len(auths) authReq := generatePersonalAuthTokenRequest() createdAuth, resp, err := client.Authorizations.Create(context.Background(), authReq) failOnError(t, err) failIfNotStatusCode(t, resp, 201) if *authReq.Note != *createdAuth.Note { t.Fatal("Returned Authorization does not match the requested Authorization.") } auths, resp, err = client.Authorizations.List(context.Background(), nil) failOnError(t, err) failIfNotStatusCode(t, resp, 200) if len(auths) != initialAuthCount+1 { t.Fatalf("The number of Authorizations should have increased. Expected [%v], was [%v]", initialAuthCount+1, len(auths)) } // Test updating the authorization authUpdate := new(github.AuthorizationUpdateRequest) authUpdate.Note = github.String("Updated note: " + randString()) updatedAuth, resp, err := client.Authorizations.Edit(context.Background(), *createdAuth.ID, authUpdate) failOnError(t, err) failIfNotStatusCode(t, resp, 200) if *updatedAuth.Note != *authUpdate.Note { t.Fatal("The returned Authorization does not match the requested updated value.") } // Verify that the Get operation also reflects the update retrievedAuth, resp, err := client.Authorizations.Get(context.Background(), *createdAuth.ID) failOnError(t, err) failIfNotStatusCode(t, resp, 200) if *retrievedAuth.Note != *updatedAuth.Note { t.Fatal("The retrieved Authorization does not match the expected (updated) value.") } // Now, let's delete... resp, err = client.Authorizations.Delete(context.Background(), *createdAuth.ID) failOnError(t, err) failIfNotStatusCode(t, resp, 204) // Verify that we can no longer retrieve the auth retrievedAuth, resp, err = client.Authorizations.Get(context.Background(), *createdAuth.ID) if err == nil { t.Fatal("Should have failed due to 404") } failIfNotStatusCode(t, resp, 404) // Verify that our count reset back to the initial value auths, resp, err = client.Authorizations.List(context.Background(), nil) failOnError(t, err) failIfNotStatusCode(t, resp, 200) if len(auths) != initialAuthCount { t.Fatalf("The number of Authorizations should match the initial count Expected [%v], got [%v]", initialAuthCount, len(auths)) } } // TestAuthorizationsAppOperations tests the application/token related operations, such // as creating, testing, resetting and revoking application OAuth tokens. func TestAuthorizationsAppOperations(t *testing.T) { userAuthenticatedClient := getUserPassClient(t) appAuthenticatedClient := getOAuthAppClient(t) // We know these vars are set because getOAuthAppClient would have // skipped the test by now clientID := os.Getenv(envKeyClientID) clientSecret := os.Getenv(envKeyClientSecret) authRequest := generateAppAuthTokenRequest(clientID, clientSecret) createdAuth, resp, err := userAuthenticatedClient.Authorizations.GetOrCreateForApp(context.Background(), clientID, authRequest) failOnError(t, err) failIfNotStatusCode(t, resp, 201) // Quick sanity check: if *createdAuth.Note != *authRequest.Note { t.Fatal("The returned auth does not match expected value.") } // Let's try the same request again, this time it should return the same // auth instead of creating a new one secondAuth, resp, err := userAuthenticatedClient.Authorizations.GetOrCreateForApp(context.Background(), clientID, authRequest) failOnError(t, err) failIfNotStatusCode(t, resp, 200) // Verify that the IDs are the same if *createdAuth.ID != *secondAuth.ID { t.Fatalf("The ID of the second returned auth should be the same as the first. Expected [%v], got [%v]", createdAuth.ID, secondAuth.ID) } // Verify the token appAuth, resp, err := appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, *createdAuth.Token) failOnError(t, err) failIfNotStatusCode(t, resp, 200) // Quick sanity check if *appAuth.ID != *createdAuth.ID || *appAuth.Token != *createdAuth.Token { t.Fatal("The returned auth/token does not match.") } // Let's verify that we get a 404 for a non-existent token _, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, InvalidTokenValue) if err == nil { t.Fatal("An error should have been returned because of the invalid token.") } failIfNotStatusCode(t, resp, 404) // Let's reset the token resetAuth, resp, err := appAuthenticatedClient.Authorizations.Reset(context.Background(), clientID, *createdAuth.Token) failOnError(t, err) failIfNotStatusCode(t, resp, 200) // Let's verify that we get a 404 for a non-existent token _, resp, err = appAuthenticatedClient.Authorizations.Reset(context.Background(), clientID, InvalidTokenValue) if err == nil { t.Fatal("An error should have been returned because of the invalid token.") } failIfNotStatusCode(t, resp, 404) // Verify that the token has changed if resetAuth.Token == createdAuth.Token { t.Fatal("The reset token should be different from the original.") } // Verify that we do have a token value if *resetAuth.Token == "" { t.Fatal("A token value should have been returned.") } // Verify that the original token is now invalid _, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, *createdAuth.Token) if err == nil { t.Fatal("The original token should be invalid.") } failIfNotStatusCode(t, resp, 404) // Check that the reset token is valid _, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, *resetAuth.Token) failOnError(t, err) failIfNotStatusCode(t, resp, 200) // Let's revoke the token resp, err = appAuthenticatedClient.Authorizations.Revoke(context.Background(), clientID, *resetAuth.Token) failOnError(t, err) failIfNotStatusCode(t, resp, 204) // Sleep for two seconds... I've seen cases where the revocation appears not // to have take place immediately. time.Sleep(time.Second * 2) // Now, the reset token should also be invalid _, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, *resetAuth.Token) if err == nil { t.Fatal("The reset token should be invalid.") } failIfNotStatusCode(t, resp, 404) } // generatePersonalAuthTokenRequest is a helper function that generates an // AuthorizationRequest for a Personal Access Token (no client id). func generatePersonalAuthTokenRequest() *github.AuthorizationRequest { rand := randString() auth := github.AuthorizationRequest{ Note: github.String("Personal token: Note generated by test: " + rand), Scopes: []github.Scope{github.ScopePublicRepo}, Fingerprint: github.String("Personal token: Fingerprint generated by test: " + rand), } return &auth } // generatePersonalAuthTokenRequest is a helper function that generates an // AuthorizationRequest for an OAuth application Token (uses client id). func generateAppAuthTokenRequest(clientID string, clientSecret string) *github.AuthorizationRequest { rand := randString() auth := github.AuthorizationRequest{ Note: github.String("App token: Note generated by test: " + rand), Scopes: []github.Scope{github.ScopePublicRepo}, Fingerprint: github.String("App token: Fingerprint generated by test: " + rand), ClientID: github.String(clientID), ClientSecret: github.String(clientSecret), } return &auth } // randString returns a (kinda) random string for uniqueness purposes. func randString() string { return strconv.FormatInt(rand.NewSource(time.Now().UnixNano()).Int63(), 10) } // failOnError invokes t.Fatal() if err is present. func failOnError(t *testing.T, err error) { if err != nil { t.Fatal(err) } } // failIfNotStatusCode invokes t.Fatal() if the response's status code doesn't match the expected code. func failIfNotStatusCode(t *testing.T, resp *github.Response, expectedCode int) { if resp.StatusCode != expectedCode { t.Fatalf("Expected HTTP status code [%v] but received [%v]", expectedCode, resp.StatusCode) } } // getUserPassClient returns a GitHub client for authorization testing. The client // uses BasicAuth via GH username and password passed in environment variables // (and will skip the calling test if those vars are not present). func getUserPassClient(t *testing.T) *github.Client { username, ok := os.LookupEnv(envKeyGitHubUsername) if !ok { t.Skipf(msgEnvMissing, envKeyGitHubUsername) } password, ok := os.LookupEnv(envKeyGitHubPassword) if !ok { t.Skipf(msgEnvMissing, envKeyGitHubPassword) } tp := github.BasicAuthTransport{ Username: strings.TrimSpace(username), Password: strings.TrimSpace(password), } return github.NewClient(tp.Client()) } // getOAuthAppClient returns a GitHub client for authorization testing. The client // uses BasicAuth, but instead of username and password, it uses the client id // and client secret passed in via environment variables // (and will skip the calling test if those vars are not present). Certain API operations (check // an authorization; reset an authorization; revoke an authorization for an app) // require this authentication mechanism. // // See GitHub API docs: https://developer.com/v3/oauth_authorizations/#check-an-authorization func getOAuthAppClient(t *testing.T) *github.Client { username, ok := os.LookupEnv(envKeyClientID) if !ok { t.Skipf(msgEnvMissing, envKeyClientID) } password, ok := os.LookupEnv(envKeyClientSecret) if !ok { t.Skipf(msgEnvMissing, envKeyClientSecret) } tp := github.BasicAuthTransport{ Username: strings.TrimSpace(username), Password: strings.TrimSpace(password), } return github.NewClient(tp.Client()) } go-github-28.1.1/test/integration/doc.go000066400000000000000000000006601353501270500200710ustar00rootroot00000000000000// 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 integration contains integration tests. // // These tests call the live GitHub API, and therefore require a little more // setup to run. See https://github.com/google/go-github/tree/master/test#integration // for more information. package integration go-github-28.1.1/test/integration/github_test.go000066400000000000000000000037201353501270500216450ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build integration package integration import ( "context" "fmt" "math/rand" "net/http" "os" "github.com/google/go-github/v28/github" "golang.org/x/oauth2" ) var ( client *github.Client // auth indicates whether tests are being run with an OAuth token. // Tests can use this flag to skip certain tests when run without auth. auth bool ) func init() { token := os.Getenv("GITHUB_AUTH_TOKEN") if token == "" { print("!!! No OAuth token. Some tests won't run. !!!\n\n") client = github.NewClient(nil) } else { tc := oauth2.NewClient(context.Background(), oauth2.StaticTokenSource( &oauth2.Token{AccessToken: token}, )) client = github.NewClient(tc) auth = true } // Environment variables required for Authorization integration tests vars := []string{envKeyGitHubUsername, envKeyGitHubPassword, envKeyClientID, envKeyClientSecret} for _, v := range vars { value := os.Getenv(v) if value == "" { print("!!! " + fmt.Sprintf(msgEnvMissing, v) + " !!!\n\n") } } } func checkAuth(name string) bool { if !auth { fmt.Printf("No auth - skipping portions of %v\n", name) } return auth } func createRandomTestRepository(owner string, autoinit bool) (*github.Repository, error) { // create random repo name that does not currently exist var repoName string for { repoName = fmt.Sprintf("test-%d", rand.Int()) _, resp, err := client.Repositories.Get(context.Background(), owner, repoName) if err != nil { if resp.StatusCode == http.StatusNotFound { // found a non-existent repo, perfect break } return nil, err } } // create the repository repo, _, err := client.Repositories.Create(context.Background(), "", &github.Repository{Name: github.String(repoName), AutoInit: github.Bool(autoinit)}) if err != nil { return nil, err } return repo, nil } go-github-28.1.1/test/integration/issues_test.go000066400000000000000000000021421353501270500216730ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build integration package integration import ( "context" "testing" ) func TestIssueEvents(t *testing.T) { events, _, err := client.Issues.ListRepositoryEvents(context.Background(), "google", "go-github", nil) if err != nil { t.Fatalf("Issues.ListRepositoryEvents returned error: %v", err) } if len(events) == 0 { t.Errorf("ListRepositoryEvents returned no events") } events, _, err = client.Issues.ListIssueEvents(context.Background(), "google", "go-github", 1, nil) if err != nil { t.Fatalf("Issues.ListIssueEvents returned error: %v", err) } if len(events) == 0 { t.Errorf("ListIssueEvents returned no events") } event, _, err := client.Issues.GetEvent(context.Background(), "google", "go-github", *events[0].ID) if err != nil { t.Fatalf("Issues.GetEvent returned error: %v", err) } if *event.URL != *events[0].URL { t.Fatalf("Issues.GetEvent returned event URL: %v, want %v", *event.URL, *events[0].URL) } } go-github-28.1.1/test/integration/misc_test.go000066400000000000000000000034001353501270500213110ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build integration package integration import ( "context" "testing" "time" ) func TestEmojis(t *testing.T) { emoji, _, err := client.ListEmojis(context.Background()) if err != nil { t.Fatalf("ListEmojis returned error: %v", err) } if len(emoji) == 0 { t.Errorf("ListEmojis returned no emojis") } if _, ok := emoji["+1"]; !ok { t.Errorf("ListEmojis missing '+1' emoji") } } func TestAPIMeta(t *testing.T) { meta, _, err := client.APIMeta(context.Background()) if err != nil { t.Fatalf("APIMeta returned error: %v", err) } if len(meta.Hooks) == 0 { t.Errorf("APIMeta returned no hook addresses") } if len(meta.Git) == 0 { t.Errorf("APIMeta returned no git addresses") } if !*meta.VerifiablePasswordAuthentication { t.Errorf("APIMeta VerifiablePasswordAuthentication is false") } } func TestRateLimits(t *testing.T) { limits, _, err := client.RateLimits(context.Background()) if err != nil { t.Fatalf("RateLimits returned error: %v", err) } // do some sanity checks if limits.Core.Limit == 0 { t.Errorf("RateLimits returned 0 core limit") } if limits.Core.Limit < limits.Core.Remaining { t.Errorf("Core.Limits is less than Core.Remaining.") } if limits.Core.Reset.Time.Before(time.Now().Add(-1 * time.Minute)) { t.Errorf("Core.Reset is more than 1 minute in the past; that doesn't seem right.") } } func TestListServiceHooks(t *testing.T) { hooks, _, err := client.ListServiceHooks(context.Background()) if err != nil { t.Fatalf("ListServiceHooks returned error: %v", err) } if len(hooks) == 0 { t.Fatalf("ListServiceHooks returned no hooks") } } go-github-28.1.1/test/integration/pulls_test.go000066400000000000000000000014141353501270500215200ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build integration package integration import ( "context" "testing" ) func TestPullRequests_ListCommits(t *testing.T) { commits, _, err := client.PullRequests.ListCommits(context.Background(), "google", "go-github", 2, nil) if err != nil { t.Fatalf("PullRequests.ListCommits() returned error: %v", err) } if got, want := len(commits), 3; got != want { t.Fatalf("PullRequests.ListCommits() returned %d commits, want %d", got, want) } if got, want := *commits[0].Author.Login, "sqs"; got != want { t.Fatalf("PullRequests.ListCommits()[0].Author.Login returned %v, want %v", got, want) } } go-github-28.1.1/test/integration/repos_test.go000066400000000000000000000127571353501270500215250ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build integration package integration import ( "context" "net/http" "reflect" "testing" "github.com/google/go-github/v28/github" ) func TestRepositories_CRUD(t *testing.T) { if !checkAuth("TestRepositories_CRUD") { return } // get authenticated user me, _, err := client.Users.Get(context.Background(), "") if err != nil { t.Fatalf("Users.Get('') returned error: %v", err) } repo, err := createRandomTestRepository(*me.Login, false) if err != nil { t.Fatalf("createRandomTestRepository returned error: %v", err) } // update the repository description repo.Description = github.String("description") repo.DefaultBranch = nil // FIXME: this shouldn't be necessary _, _, err = client.Repositories.Edit(context.Background(), *repo.Owner.Login, *repo.Name, repo) if err != nil { t.Fatalf("Repositories.Edit() returned error: %v", err) } // delete the repository _, err = client.Repositories.Delete(context.Background(), *repo.Owner.Login, *repo.Name) if err != nil { t.Fatalf("Repositories.Delete() returned error: %v", err) } // verify that the repository was deleted _, resp, err := client.Repositories.Get(context.Background(), *repo.Owner.Login, *repo.Name) if err == nil { t.Fatalf("Test repository still exists after deleting it.") } if err != nil && resp.StatusCode != http.StatusNotFound { t.Fatalf("Repositories.Get() returned error: %v", err) } } func TestRepositories_BranchesTags(t *testing.T) { // branches branches, _, err := client.Repositories.ListBranches(context.Background(), "git", "git", nil) if err != nil { t.Fatalf("Repositories.ListBranches() returned error: %v", err) } if len(branches) == 0 { t.Fatalf("Repositories.ListBranches('git', 'git') returned no branches") } _, _, err = client.Repositories.GetBranch(context.Background(), "git", "git", *branches[0].Name) if err != nil { t.Fatalf("Repositories.GetBranch() returned error: %v", err) } // tags tags, _, err := client.Repositories.ListTags(context.Background(), "git", "git", nil) if err != nil { t.Fatalf("Repositories.ListTags() returned error: %v", err) } if len(tags) == 0 { t.Fatalf("Repositories.ListTags('git', 'git') returned no tags") } } func TestRepositories_EditBranches(t *testing.T) { if !checkAuth("TestRepositories_EditBranches") { return } // get authenticated user me, _, err := client.Users.Get(context.Background(), "") if err != nil { t.Fatalf("Users.Get('') returned error: %v", err) } repo, err := createRandomTestRepository(*me.Login, true) if err != nil { t.Fatalf("createRandomTestRepository returned error: %v", err) } branch, _, err := client.Repositories.GetBranch(context.Background(), *repo.Owner.Login, *repo.Name, "master") if err != nil { t.Fatalf("Repositories.GetBranch() returned error: %v", err) } if *branch.Protected { t.Fatalf("Branch %v of repo %v is already protected", "master", *repo.Name) } protectionRequest := &github.ProtectionRequest{ RequiredStatusChecks: &github.RequiredStatusChecks{ Strict: true, Contexts: []string{"continuous-integration"}, }, RequiredPullRequestReviews: &github.PullRequestReviewsEnforcementRequest{ DismissStaleReviews: true, }, EnforceAdmins: true, // TODO: Only organization repositories can have users and team restrictions. // In order to be able to test these Restrictions, need to add support // for creating temporary organization repositories. Restrictions: nil, } protection, _, err := client.Repositories.UpdateBranchProtection(context.Background(), *repo.Owner.Login, *repo.Name, "master", protectionRequest) if err != nil { t.Fatalf("Repositories.UpdateBranchProtection() returned error: %v", err) } want := &github.Protection{ RequiredStatusChecks: &github.RequiredStatusChecks{ Strict: true, Contexts: []string{"continuous-integration"}, }, RequiredPullRequestReviews: &github.PullRequestReviewsEnforcement{ DismissStaleReviews: true, RequiredApprovingReviewCount: 0, }, EnforceAdmins: &github.AdminEnforcement{ URL: github.String("https://api.github.com/repos/" + *repo.Owner.Login + "/" + *repo.Name + "/branches/master/protection/enforce_admins"), Enabled: true, }, Restrictions: nil, } if !reflect.DeepEqual(protection, want) { t.Errorf("Repositories.UpdateBranchProtection() returned %+v, want %+v", protection, want) } _, err = client.Repositories.Delete(context.Background(), *repo.Owner.Login, *repo.Name) if err != nil { t.Fatalf("Repositories.Delete() returned error: %v", err) } } func TestRepositories_List(t *testing.T) { if !checkAuth("TestRepositories_List") { return } _, _, err := client.Repositories.List(context.Background(), "", nil) if err != nil { t.Fatalf("Repositories.List('') returned error: %v", err) } _, _, err = client.Repositories.List(context.Background(), "google", nil) if err != nil { t.Fatalf("Repositories.List('google') returned error: %v", err) } opt := github.RepositoryListOptions{Sort: "created"} repos, _, err := client.Repositories.List(context.Background(), "google", &opt) if err != nil { t.Fatalf("Repositories.List('google') with Sort opt returned error: %v", err) } for i, repo := range repos { if i > 0 && (*repos[i-1].CreatedAt).Time.Before((*repo.CreatedAt).Time) { t.Fatalf("Repositories.List('google') with default descending Sort returned incorrect order") } } } go-github-28.1.1/test/integration/users_test.go000066400000000000000000000145331353501270500215300ustar00rootroot00000000000000// Copyright 2014 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build integration package integration import ( "context" "fmt" "math/rand" "testing" "github.com/google/go-github/v28/github" ) func TestUsers_Get(t *testing.T) { // list all users users, _, err := client.Users.ListAll(context.Background(), nil) if err != nil { t.Fatalf("Users.ListAll returned error: %v", err) } if len(users) == 0 { t.Errorf("Users.ListAll returned no users") } // mojombo is user #1 if want := "mojombo"; want != *users[0].Login { t.Errorf("user[0].Login was %q, wanted %q", *users[0].Login, want) } // get individual user u, _, err := client.Users.Get(context.Background(), "octocat") if err != nil { t.Fatalf("Users.Get('octocat') returned error: %v", err) } if want := "octocat"; want != *u.Login { t.Errorf("user.Login was %q, wanted %q", *u.Login, want) } if want := "The Octocat"; want != *u.Name { t.Errorf("user.Name was %q, wanted %q", *u.Name, want) } } func TestUsers_Update(t *testing.T) { if !checkAuth("TestUsers_Get") { return } u, _, err := client.Users.Get(context.Background(), "") if err != nil { t.Fatalf("Users.Get('') returned error: %v", err) } if *u.Login == "" { t.Errorf("wanted non-empty values for user.Login") } // save original location var location string if u.Location != nil { location = *u.Location } // update location to test value testLoc := fmt.Sprintf("test-%d", rand.Int()) u.Location = &testLoc _, _, err = client.Users.Edit(context.Background(), u) if err != nil { t.Fatalf("Users.Update returned error: %v", err) } // refetch user and check location value u, _, err = client.Users.Get(context.Background(), "") if err != nil { t.Fatalf("Users.Get('') returned error: %v", err) } if testLoc != *u.Location { t.Errorf("Users.Get('') has location: %v, want: %v", *u.Location, testLoc) } // set location back to the original value u.Location = &location _, _, err = client.Users.Edit(context.Background(), u) if err != nil { t.Fatalf("Users.Edit returned error: %v", err) } } func TestUsers_Emails(t *testing.T) { if !checkAuth("TestUsers_Emails") { return } emails, _, err := client.Users.ListEmails(context.Background(), nil) if err != nil { t.Fatalf("Users.ListEmails() returned error: %v", err) } // create random address not currently in user's emails var email string EmailLoop: for { email = fmt.Sprintf("test-%d@example.com", rand.Int()) for _, e := range emails { if e.Email != nil && *e.Email == email { continue EmailLoop } } break } // Add new address _, _, err = client.Users.AddEmails(context.Background(), []string{email}) if err != nil { t.Fatalf("Users.AddEmails() returned error: %v", err) } // List emails again and verify new email is present emails, _, err = client.Users.ListEmails(context.Background(), nil) if err != nil { t.Fatalf("Users.ListEmails() returned error: %v", err) } var found bool for _, e := range emails { if e.Email != nil && *e.Email == email { found = true break } } if !found { t.Fatalf("Users.ListEmails() does not contain new address: %v", email) } // Remove new address _, err = client.Users.DeleteEmails(context.Background(), []string{email}) if err != nil { t.Fatalf("Users.DeleteEmails() returned error: %v", err) } // List emails again and verify new email was removed emails, _, err = client.Users.ListEmails(context.Background(), nil) if err != nil { t.Fatalf("Users.ListEmails() returned error: %v", err) } for _, e := range emails { if e.Email != nil && *e.Email == email { t.Fatalf("Users.ListEmails() still contains address %v after removing it", email) } } } func TestUsers_Keys(t *testing.T) { keys, _, err := client.Users.ListKeys(context.Background(), "willnorris", nil) if err != nil { t.Fatalf("Users.ListKeys('willnorris') returned error: %v", err) } if len(keys) == 0 { t.Errorf("Users.ListKeys('willnorris') returned no keys") } // the rest of the tests requires auth if !checkAuth("TestUsers_Keys") { return } // TODO: make this integration test work for any authenticated user. keys, _, err = client.Users.ListKeys(context.Background(), "", nil) if err != nil { t.Fatalf("Users.ListKeys('') returned error: %v", err) } // ssh public key for testing (fingerprint: a7:22:ad:8c:36:9f:68:65:eb:ae:a1:e4:59:73:c1:76) key := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCy/RIqaMFj2wjkOEjx9EAU0ReLAIhodga82/feo5nnT9UUkHLbL9xrIavfdLHx28lD3xYgPfAoSicUMaAeNwuQhmuerr2c2LFGxzrdXP8pVsQ+Ol7y7OdmFPfe0KrzoZaLJs9aSiZ4VKyY4z5Se/k2UgcJTdgQVlLfw/P96aqCx8yUu94BiWqkDqYEvgWKRNHrTiIo1EXeVBCCcfgNZe1suFfNJUJSUU2T3EG2bpwBbSOCjE3FyH8+Lz3K3BOGzm3df8E7Regj9j4YIcD8cWJYO86jLJoGgQ0L5MSOq+ishNaHQXech22Ix03D1lVMjCvDT7S/C94Z1LzhI2lhvyff" for _, k := range keys { if k.Key != nil && *k.Key == key { t.Fatalf("Test key already exists for user. Please manually remove it first.") } } // Add new key _, _, err = client.Users.CreateKey(context.Background(), &github.Key{ Title: github.String("go-github test key"), Key: github.String(key), }) if err != nil { t.Fatalf("Users.CreateKey() returned error: %v", err) } // List keys again and verify new key is present keys, _, err = client.Users.ListKeys(context.Background(), "", nil) if err != nil { t.Fatalf("Users.ListKeys('') returned error: %v", err) } var id int64 for _, k := range keys { if k.Key != nil && *k.Key == key { id = *k.ID break } } if id == 0 { t.Fatalf("Users.ListKeys('') does not contain added test key") } // Verify that fetching individual key works k, _, err := client.Users.GetKey(context.Background(), id) if err != nil { t.Fatalf("Users.GetKey(%q) returned error: %v", id, err) } if *k.Key != key { t.Fatalf("Users.GetKey(%q) returned key %v, want %v", id, *k.Key, key) } // Remove test key _, err = client.Users.DeleteKey(context.Background(), id) if err != nil { t.Fatalf("Users.DeleteKey(%d) returned error: %v", id, err) } // List keys again and verify test key was removed keys, _, err = client.Users.ListKeys(context.Background(), "", nil) if err != nil { t.Fatalf("Users.ListKeys('') returned error: %v", err) } for _, k := range keys { if k.Key != nil && *k.Key == key { t.Fatalf("Users.ListKeys('') still contains test key after removing it") } } }