Skip to content

Commit

Permalink
# This is a combination of 23 commits.
Browse files Browse the repository at this point in the history
# This is the 1st commit message:

app name first

# This is the commit message nazzzzz#2:

clean up file

# This is the commit message nazzzzz#3:

fix reference to proto package

# This is the commit message fasterci#4:

better parse

# This is the commit message fasterci#5:

fix again

# This is the commit message fasterci#6:

fix again

# This is the commit message fasterci#7:

fix again

# This is the commit message fasterci#8:

fix again

# This is the commit message fasterci#9:

fix again

# This is the commit message fasterci#10:

fix again

# This is the commit message fasterci#11:

add debug statements for seeing if branch is dirty

# This is the commit message fasterci#12:

fix again

# This is the commit message fasterci#13:

fix again

# This is the commit message fasterci#14:

fix again

# This is the commit message fasterci#15:

fix again

# This is the commit message fasterci#16:

fix again

# This is the commit message fasterci#17:

fix again

# This is the commit message fasterci#18:

fix again

# This is the commit message fasterci#19:

fix again

# This is the commit message fasterci#20:

fix again

# This is the commit message fasterci#21:

fix again

# This is the commit message fasterci#22:

fix again

# This is the commit message fasterci#23:

fix again
  • Loading branch information
nazzzzz authored and shraykay committed Jan 22, 2025
1 parent 252a0bb commit 503f475
Show file tree
Hide file tree
Showing 367 changed files with 38,362 additions and 1,344 deletions.
2 changes: 1 addition & 1 deletion MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 31 additions & 4 deletions gitops/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,11 @@ import (
"os"
oe "os/exec"
"path/filepath"
"strings"

"github.com/fasterci/rules_gitops/gitops/exec"
)

var (
git = "git"
)

// Clone clones a repository. Pass the full repository name, such as
// "https://[email protected]/scm/tm/repo.git" as the repo.
// Cloned directory will be clean of local changes with primaryBranch branch checked out.
Expand Down Expand Up @@ -120,3 +117,33 @@ func (r *Repo) Push(branches []string) {
args := append([]string{"push", "origin", "-f", "--set-upstream"}, branches...)
exec.Mustex(r.Dir, "git", args...)
}

func (r *Repo) GetModifiedFiles() ([]string, error) {
cmd := oe.Command("git", "status", "--porcelain")
cmd.Dir = r.Dir
output, err := cmd.CombinedOutput()
if err != nil {
return nil, fmt.Errorf("failed to get modified files: %w", err)
}

if len(output) == 0 {
return []string{}, nil
}

// Split output into lines and process each line
lines := strings.Split(strings.TrimSpace(string(output)), "\n")
files := make([]string, 0, len(lines))

for _, line := range lines {
if len(line) > 3 {
// git status --porcelain output format is "XY filename"
// where X and Y are status codes
// We just want the filename part
file := strings.TrimSpace(line[2:])
files = append(files, file)
log.Printf("Modified file: %s", file)
}
}

return files, nil
}
1 change: 1 addition & 0 deletions gitops/git/github_app/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ go_library(
importpath = "github.com/fasterci/rules_gitops/gitops/git/github_app",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/ProtonMail/go-crypto/openpgp:go_default_library",
"//vendor/github.com/bradleyfalzon/ghinstallation/v2:go_default_library",
"//vendor/github.com/google/go-github/v58/github:go_default_library",
],
Expand Down
128 changes: 126 additions & 2 deletions gitops/git/github_app/github_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import (
"context"
"errors"
"flag"
"io/ioutil"
"io"
"log"
"net/http"
"os"
"path/filepath"
"time"

"github.com/bradleyfalzon/ghinstallation/v2"
"github.com/google/go-github/v58/github"
Expand All @@ -21,6 +24,7 @@ var (
gitHubAppId = flag.Int64("github_app_id", 1014336, "GitHub App Id")
gitHubAppInstallationId = flag.Int64("github_installation_id", 0, "GitHub App Id")
gitHubUser = flag.String("github_user", "etsy", "GitHub User")
githubEmail = flag.String("github_email", "", "GitHub Email")
gitHubAppName = flag.String("github_app_name", "gitops-pr-creator", "Name of the GitHub App")
)

Expand Down Expand Up @@ -81,7 +85,7 @@ func CreatePR(from, to, title, body string) error {

// All other github responses
defer resp.Body.Close()
responseBody, readingErr := ioutil.ReadAll(resp.Body)
responseBody, readingErr := io.ReadAll(resp.Body)
if readingErr != nil {
log.Println("cannot read response body")
} else {
Expand All @@ -90,3 +94,123 @@ func CreatePR(from, to, title, body string) error {

return err
}

func CreateCommit(baseBranch string, commitBranch string, gitopsPath string, files []string, commitMsg string) {
ctx := context.Background()
gh := createGithubClient()

ref := getRef(ctx, gh, baseBranch, commitBranch)
tree, err := getTree(ctx, gh, ref, gitopsPath, files)
if err != nil {
log.Fatalf("failed to create tree: %v", err)
}

pushCommit(ctx, gh, ref, tree, commitMsg, *githubEmail)
createPR(ctx, gh, baseBranch, commitBranch, commitMsg, "")
}

func createPR(ctx context.Context, gh *github.Client, baseBranch string, commitBranch string, prSubject string, prDescription string) {
newPR := &github.NewPullRequest{
Title: &prSubject,
Head: &commitBranch,
HeadRepo: &baseBranch,
Base: &baseBranch,
Body: &prDescription,
MaintainerCanModify: github.Bool(true),
}

pr, _, err := gh.PullRequests.Create(ctx, *repoOwner, *repo, newPR)
if err != nil {
log.Fatalf("failed to create PR: %v", err)
}

log.Printf("PR created: %s\n", pr.GetHTMLURL())
}

func createGithubClient() *github.Client {
if *repoOwner == "" {
log.Fatal("github_app_repo_owner must be set")
}
if *repo == "" {
log.Fatal("github_app_repo must be set")
}
if *gitHubAppId == 0 {
log.Fatal("github_app_id must be set")
}

// get an installation token request handler for the github app
itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, *gitHubAppId, *gitHubAppInstallationId, *privateKey)
if err != nil {
log.Println("failed reading key", "key", *privateKey, "err", err)
log.Fatal(err)
}

return github.NewClient(&http.Client{Transport: itr})
}

func getRef(ctx context.Context, gh *github.Client, baseBranch string, commitBranch string) *github.Reference {
// get the reference if the branch already exists
if ref, _, err := gh.Git.GetRef(ctx, *repoOwner, *repo, "refs/heads/"+commitBranch); err == nil {
return ref
}

baseRef, _, err := gh.Git.GetRef(ctx, *repoOwner, *repo, "refs/heads/"+baseBranch)

if err != nil {
log.Fatalf("failed to get base branch ref: %v", err)
}

newRef := &github.Reference{Ref: github.String("refs/heads/" + commitBranch), Object: &github.GitObject{SHA: baseRef.Object.SHA}}
ref, _, err := gh.Git.CreateRef(ctx, *repoOwner, *repo, newRef)
if err != nil {
log.Fatalf("failed to create branch ref: %v", err)
}
return ref
}

func getTree(ctx context.Context, gh *github.Client, ref *github.Reference, gitopsPath string, filePaths []string) (tree *github.Tree, err error) {
// Create a tree with what to commit.
entries := []*github.TreeEntry{}

// Load each file into the tree.
for _, file := range filePaths {
fullPath := filepath.Join(gitopsPath, file)
content, err := os.ReadFile(fullPath)
if err != nil {
log.Fatalf("failed to read file %s: %v", fullPath, 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 = gh.Git.CreateTree(ctx, *repoOwner, *repo, *ref.Object.SHA, entries)
return tree, err
}

func pushCommit(ctx context.Context, gh *github.Client, ref *github.Reference, tree *github.Tree, commitMessage string, authorEmail string) {
// Get the parent commit to attach the commit to.
parent, _, err := gh.Repositories.GetCommit(ctx, *repoOwner, *repo, *ref.Object.SHA, nil)
if err != nil {
log.Fatalf("failed to get parent commit: %v", 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: &github.Timestamp{Time: date}, Name: gitHubAppName, Email: &authorEmail}
commit := &github.Commit{Author: author, Message: &commitMessage, Tree: tree, Parents: []*github.Commit{parent.Commit}}
opts := github.CreateCommitOptions{}

newCommit, _, err := gh.Git.CreateCommit(ctx, *repoOwner, *repo, commit, &opts)
if err != nil {
log.Fatalf("failed to create commit: %v", err)
}

// Attach the commit to the master branch.
ref.Object.SHA = newCommit.SHA
_, _, err = gh.Git.UpdateRef(ctx, *repoOwner, *repo, ref, false)
if err != nil {
log.Fatalf("failed to update ref: %v", err)
}
}
Loading

0 comments on commit 503f475

Please sign in to comment.