grafana/pkg/services/store/github_helper.go
2022-07-28 23:26:44 -07:00

183 lines
5.0 KiB
Go

package store
import (
"context"
"fmt"
"net/url"
"strings"
"time"
"github.com/google/go-github/v45/github"
"golang.org/x/oauth2"
)
type githubHelper struct {
repoOwner string
repoName string
client *github.Client
}
func newGithubHelper(ctx context.Context, uri string, token string) (*githubHelper, error) {
v, err := url.Parse(uri)
if err != nil {
return nil, err
}
path := strings.TrimPrefix(v.Path, "/")
path = strings.TrimSuffix(path, ".git")
idx := strings.Index(path, "/")
if idx < 1 {
return nil, fmt.Errorf("invalid url")
}
if token == "" {
return nil, fmt.Errorf("unauthorized: No token present")
}
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
tc := oauth2.NewClient(ctx, ts)
return &githubHelper{
client: github.NewClient(tc),
repoOwner: path[:idx],
repoName: path[idx+1:],
}, nil
}
func (g *githubHelper) getRef(ctx context.Context, branch string) (*github.Reference, *github.Response, error) {
return g.client.Git.GetRef(ctx, g.repoOwner, g.repoName, "refs/heads/"+branch)
}
func (g *githubHelper) createRef(ctx context.Context, base string, branch string) (ref *github.Reference, rsp *github.Response, err error) {
var baseRef *github.Reference
if baseRef, rsp, err = g.client.Git.GetRef(ctx, g.repoOwner, g.repoName, "refs/heads/"+base); err != nil {
return nil, rsp, err
}
newRef := &github.Reference{
Ref: github.String("refs/heads/" + branch),
Object: &github.GitObject{SHA: baseRef.Object.SHA},
}
return g.client.Git.CreateRef(ctx, g.repoOwner, g.repoName, newRef)
}
func (g *githubHelper) getRepo(ctx context.Context) (*github.Repository, *github.Response, error) {
return g.client.Repositories.Get(ctx, g.repoOwner, g.repoName)
}
// pushCommit creates the commit in the given reference using the given tree.
func (g *githubHelper) pushCommit(ctx context.Context, ref *github.Reference, cmd *WriteValueRequest) (err error) {
// Create a tree with what to commit.
entries := []*github.TreeEntry{
{
Path: github.String(cmd.Path),
Type: github.String("blob"),
Content: github.String(string(cmd.Body)),
Mode: github.String("100644"),
},
}
tree, _, err := g.client.Git.CreateTree(ctx, g.repoOwner, g.repoName, *ref.Object.SHA, entries)
if err != nil {
return err
}
// Get the parent commit to attach the commit to.
parent, _, err := g.client.Repositories.GetCommit(ctx, g.repoOwner, g.repoName, *ref.Object.SHA, nil)
if err != nil {
return err
}
// This is not always populated, but is needed.
parent.Commit.SHA = parent.SHA
user := cmd.User
name := firstRealString(user.Name, user.Login, user.Email, "?")
email := firstRealString(user.Email, user.Login, user.Name, "?")
// Create the commit using the tree.
date := time.Now()
author := &github.CommitAuthor{
Date: &date,
Name: &name,
Email: &email,
}
commit := &github.Commit{Author: author, Message: &cmd.Message, Tree: tree, Parents: []*github.Commit{parent.Commit}}
newCommit, _, err := g.client.Git.CreateCommit(ctx, g.repoOwner, g.repoName, commit)
if err != nil {
return err
}
// Attach the commit to the main branch.
ref.Object.SHA = newCommit.SHA
_, _, err = g.client.Git.UpdateRef(ctx, g.repoOwner, g.repoName, ref, false)
return err
}
type makePRCommand struct {
title string
body string
headBranch string
baseBranch string
}
func (g *githubHelper) createPR(ctx context.Context, cmd makePRCommand) (*github.PullRequest, *github.Response, error) {
newPR := &github.NewPullRequest{
Title: &cmd.title,
Head: &cmd.headBranch,
Base: &cmd.baseBranch,
Body: &cmd.body,
MaintainerCanModify: github.Bool(true),
}
return g.client.PullRequests.Create(ctx, g.repoOwner, g.repoName, newPR)
}
// func (g *githubHelper) getPR(config *Config, prSubject string) (*github.PullRequest, error) {
// opts := github.PullRequestListOptions{}
// prs, _, err := githubClient.PullRequests.List(ctx, config.RepoOwner, config.RepoName, &opts)
// if err != nil {
// return nil, err
// }
// for _, pr := range prs {
// log.Printf("PR: %s %s", *pr.Title, prSubject)
// if *pr.Title == prSubject {
// return pr, nil
// }
// }
// return nil, nil
// }
// func (g *githubHelper) pushPR(config *Config, prSubject, prBranch, prFilename, prContent, commitMessage string) error {
// pr, err := getPR(config, prSubject)
// if err != nil {
// return err
// }
// if pr != nil {
// log.Println("Extending Existing PR", *pr.Title)
// ref, err := getRef(config, pr.GetHead().GetRef())
// if err != nil {
// return err
// }
// err = pushCommit(config, ref, prFilename, prContent, commitMessage)
// if err != nil {
// return err
// }
// } else {
// log.Println("Creating PR")
// ref, err := createRef(config, prBranch)
// if err != nil {
// return err
// }
// err = pushCommit(config, ref, prFilename, prContent, commitMessage)
// if err != nil {
// return err
// }
// pr, err = createPR(config, prSubject, prBranch)
// if err != nil {
// return err
// }
// }
// return nil
// }