mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
While spamming refresh on a pull request today to see if required builds finished yet, it occurred to me that it'd be awesome to have WTF tell me when a PR was ready to be merged. So, here it is! An icon will now display next to PRs in the "My Pull Requests" section detailing whether GitHub thinks they can be merged. This is behind a new, opt-in config flag called "enableStatus", due to the fact that in order to function, this feature has to hit the GitHub API individually for each PR in order to get an updated status check - there's a comment in the code with a link that explains why (otherwise, `pr.GetMergeableState()` returns an empty string). For a large number of PRs, this can slow down refreshes a bit and _might_ even wind up rate limiting you (while testing I had some instances of GH refusing to return me any repository info, though it didn't actually give me an error, usually after I had been spamming it with requests for 30 PRs in a row for a bit). So, for that reason, use at your own risk (but it's probably fine). I am not an emoji expert, so suggestions on the display are welcome if you can think of anything awesome. A lot of the ones I tried seemed to render funny and mess up spacing.
184 lines
3.9 KiB
Go
184 lines
3.9 KiB
Go
package github
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"os"
|
|
|
|
ghb "github.com/google/go-github/github"
|
|
"golang.org/x/oauth2"
|
|
)
|
|
|
|
type GithubRepo struct {
|
|
apiKey string
|
|
baseURL string
|
|
uploadURL string
|
|
|
|
Name string
|
|
Owner string
|
|
PullRequests []*ghb.PullRequest
|
|
RemoteRepo *ghb.Repository
|
|
}
|
|
|
|
func NewGithubRepo(name, owner string) *GithubRepo {
|
|
repo := GithubRepo{
|
|
apiKey: os.Getenv("WTF_GITHUB_TOKEN"),
|
|
baseURL: os.Getenv("WTF_GITHUB_BASE_URL"),
|
|
uploadURL: os.Getenv("WTF_GITHUB_UPLOAD_URL"),
|
|
|
|
Name: name,
|
|
Owner: owner,
|
|
}
|
|
|
|
return &repo
|
|
}
|
|
|
|
// Refresh reloads the github data via the Github API
|
|
func (repo *GithubRepo) Refresh() {
|
|
repo.PullRequests, _ = repo.loadPullRequests()
|
|
repo.RemoteRepo, _ = repo.loadRemoteRepository()
|
|
}
|
|
|
|
/* -------------------- Counts -------------------- */
|
|
|
|
func (repo *GithubRepo) IssueCount() int {
|
|
if repo.RemoteRepo == nil {
|
|
return 0
|
|
}
|
|
|
|
return *repo.RemoteRepo.OpenIssuesCount
|
|
}
|
|
|
|
func (repo *GithubRepo) PullRequestCount() int {
|
|
return len(repo.PullRequests)
|
|
}
|
|
|
|
func (repo *GithubRepo) StarCount() int {
|
|
if repo.RemoteRepo == nil {
|
|
return 0
|
|
}
|
|
|
|
return *repo.RemoteRepo.StargazersCount
|
|
}
|
|
|
|
/* -------------------- Unexported Functions -------------------- */
|
|
|
|
func (repo *GithubRepo) isGitHubEnterprise() bool {
|
|
if len(repo.baseURL) > 0 {
|
|
if len(repo.uploadURL) == 0 {
|
|
repo.uploadURL = repo.baseURL
|
|
}
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (repo *GithubRepo) oauthClient() *http.Client {
|
|
tokenService := oauth2.StaticTokenSource(
|
|
&oauth2.Token{AccessToken: repo.apiKey},
|
|
)
|
|
|
|
return oauth2.NewClient(context.Background(), tokenService)
|
|
}
|
|
|
|
func (repo *GithubRepo) githubClient() (*ghb.Client, error) {
|
|
oauthClient := repo.oauthClient()
|
|
|
|
if repo.isGitHubEnterprise() {
|
|
return ghb.NewEnterpriseClient(repo.baseURL, repo.uploadURL, oauthClient)
|
|
}
|
|
|
|
return ghb.NewClient(oauthClient), nil
|
|
}
|
|
|
|
// myPullRequests returns a list of pull requests created by username on this repo
|
|
func (repo *GithubRepo) myPullRequests(username string) []*ghb.PullRequest {
|
|
prs := []*ghb.PullRequest{}
|
|
|
|
for _, pr := range repo.PullRequests {
|
|
user := *pr.User
|
|
|
|
if *user.Login == username {
|
|
prs = append(prs, pr)
|
|
}
|
|
}
|
|
|
|
if showStatus() {
|
|
prs = repo.individualPRs(prs)
|
|
}
|
|
|
|
return prs
|
|
}
|
|
|
|
// individualPRs takes a list of pull requests (presumably returned from
|
|
// github.PullRequests.List) and fetches them individually to get more detailed
|
|
// status info on each. see: https://developer.github.com/v3/git/#checking-mergeability-of-pull-requests
|
|
func (repo *GithubRepo) individualPRs(prs []*ghb.PullRequest) []*ghb.PullRequest {
|
|
github, err := repo.githubClient()
|
|
if err != nil {
|
|
return prs
|
|
}
|
|
|
|
var ret []*ghb.PullRequest
|
|
for i := range prs {
|
|
pr, _, err := github.PullRequests.Get(context.Background(), repo.Owner, repo.Name, prs[i].GetNumber())
|
|
if err != nil {
|
|
// worst case, just keep the original one
|
|
ret = append(ret, prs[i])
|
|
} else {
|
|
ret = append(ret, pr)
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// myReviewRequests returns a list of pull requests for which username has been
|
|
// requested to do a code review
|
|
func (repo *GithubRepo) myReviewRequests(username string) []*ghb.PullRequest {
|
|
prs := []*ghb.PullRequest{}
|
|
|
|
for _, pr := range repo.PullRequests {
|
|
for _, reviewer := range pr.RequestedReviewers {
|
|
if *reviewer.Login == username {
|
|
prs = append(prs, pr)
|
|
}
|
|
}
|
|
}
|
|
|
|
return prs
|
|
}
|
|
|
|
func (repo *GithubRepo) loadPullRequests() ([]*ghb.PullRequest, error) {
|
|
github, err := repo.githubClient()
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
opts := &ghb.PullRequestListOptions{}
|
|
|
|
prs, _, err := github.PullRequests.List(context.Background(), repo.Owner, repo.Name, opts)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return prs, nil
|
|
}
|
|
|
|
func (repo *GithubRepo) loadRemoteRepository() (*ghb.Repository, error) {
|
|
github, err := repo.githubClient()
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
repository, _, err := github.Repositories.Get(context.Background(), repo.Owner, repo.Name)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return repository, nil
|
|
}
|