github.com/mentimeter/morty@v1.2.2-0.20221012065510-5596adecd154/mortems/git_service.go (about)

     1  package mortems
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/google/go-github/v35/github"
    10  	"golang.org/x/oauth2"
    11  )
    12  
    13  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . RepoFileService
    14  
    15  type RepoFileService interface {
    16  	GetFiles() (*RepoFiles, error)
    17  	CommitNewFiles(*RepoFiles) error
    18  }
    19  
    20  type GitHub struct {
    21  	client        *github.Client
    22  	ref           string
    23  	owner         string
    24  	repository    string
    25  	currentTree   *github.Tree
    26  	currentCommit *github.Commit
    27  	currentRef    *github.Reference
    28  }
    29  
    30  func NewGitHubService(token, fullRepository, ref string) RepoFileService {
    31  	ctx := context.Background()
    32  	ts := oauth2.StaticTokenSource(
    33  		&oauth2.Token{AccessToken: token},
    34  	)
    35  	tc := oauth2.NewClient(ctx, ts)
    36  	client := github.NewClient(tc)
    37  	repositoryArgs := strings.Split(fullRepository, "/")
    38  
    39  	return &GitHub{
    40  		client:     client,
    41  		ref:        ref,
    42  		owner:      repositoryArgs[0],
    43  		repository: repositoryArgs[1],
    44  	}
    45  }
    46  
    47  func (g *GitHub) GetFiles() (*RepoFiles, error) {
    48  	ctx := context.Background()
    49  
    50  	ref, _, err := g.client.Git.GetRef(ctx, g.owner, g.repository, g.ref)
    51  	if err != nil {
    52  		return nil, fmt.Errorf("could not get ref: %w", err)
    53  	}
    54  
    55  	g.currentRef = ref
    56  
    57  	commit, _, err := g.client.Git.GetCommit(ctx, g.owner, g.repository, ref.Object.GetSHA())
    58  	if err != nil {
    59  		return nil, fmt.Errorf("could not get commit: %w", err)
    60  	}
    61  
    62  	g.currentCommit = commit
    63  
    64  	tree, _, err := g.client.Git.GetTree(ctx, g.owner, g.repository, commit.GetTree().GetSHA(), true)
    65  	if err != nil {
    66  		return nil, fmt.Errorf("could not get tree: %w", err)
    67  	}
    68  
    69  	g.currentTree = tree
    70  
    71  	var files []*File
    72  
    73  	for _, entry := range tree.Entries {
    74  		if entry.GetType() == "blob" {
    75  			content, _, err := g.client.Git.GetBlobRaw(ctx, g.owner, g.repository, entry.GetSHA())
    76  			if err != nil {
    77  				return nil, fmt.Errorf("could not get blob content: %w", err)
    78  			}
    79  
    80  			entry.Content = github.String(string(content))
    81  
    82  			file := &File{
    83  				Path:    *entry.Path,
    84  				Mode:    *entry.Mode,
    85  				Type:    "blob",
    86  				Content: string(content),
    87  			}
    88  
    89  			files = append(files, file)
    90  		}
    91  	}
    92  
    93  	return &RepoFiles{files}, nil
    94  }
    95  
    96  func (g *GitHub) CommitNewFiles(updateEntries *RepoFiles) error {
    97  	ctx := context.Background()
    98  
    99  	newTree, _, err := g.client.Git.CreateTree(ctx, g.owner, g.repository, g.currentTree.GetSHA(), updateEntries.ToTreeEntries())
   100  	if err != nil {
   101  		return fmt.Errorf("could not create a new tree: %w", err)
   102  	}
   103  
   104  	authorDate := time.Now()
   105  	author := &github.CommitAuthor{
   106  		Date:  &authorDate,
   107  		Name:  g.currentCommit.Author.Name,
   108  		Email: g.currentCommit.Author.Email,
   109  	}
   110  
   111  	newCommitData := &github.Commit{
   112  		Author:    author,
   113  		Committer: author,
   114  		Message:   github.String("Auto-morty-cally analyse post-mortems"),
   115  		Tree:      newTree,
   116  		Parents:   []*github.Commit{g.currentCommit},
   117  	}
   118  
   119  	createdCommit, _, err := g.client.Git.CreateCommit(ctx, g.owner, g.repository, newCommitData)
   120  	if err != nil {
   121  		return fmt.Errorf("could not create a new commit: %w", err)
   122  	}
   123  
   124  	g.currentRef.Object.SHA = createdCommit.SHA
   125  
   126  	_, _, err = g.client.Git.UpdateRef(ctx, g.owner, g.repository, g.currentRef, false)
   127  	if err != nil {
   128  		return fmt.Errorf("could not update the current ref: %w", err)
   129  	}
   130  
   131  	return nil
   132  }