mirror of
https://github.com/grafana/grafana.git
synced 2026-08-18 17:15:08 -05:00
Storage: support git + github backed roots (#52192)
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
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
|
||||
// }
|
||||
Reference in New Issue
Block a user