with actual push

This commit is contained in:
Kasper Juul Hermansen 2022-09-12 22:05:06 +02:00
parent 56bfba5c17
commit b1094294b5
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
4 changed files with 164 additions and 35 deletions

View File

@ -78,6 +78,13 @@ func (pr *ProcessRepos) Process(ctx context.Context, repositoryUrls []string) er
return return
} }
err = pr.git.CreateBranch(ctx, repo)
if err != nil {
pr.logger.Error("could not create branch", zap.Error(err))
errChan <- err
return
}
err = pr.action.Run( err = pr.action.Run(
ctx, ctx,
area, area,
@ -116,13 +123,19 @@ func (pr *ProcessRepos) Process(ctx context.Context, repositoryUrls []string) er
return nil return nil
}, false) }, false)
if err != nil { if err != nil {
pr.logger.Error("could not run action", zap.Error(err)) pr.logger.Error("could not run action", zap.Error(err))
errChan <- err errChan <- err
return return
} }
err = pr.git.Push(ctx, repo)
if err != nil {
pr.logger.Error("could not push to repo", zap.Error(err))
errChan <- err
return
}
pr.logger.Debug("processing done", zap.String("path", area.Path), zap.String("repoUrl", repoUrl)) pr.logger.Debug("processing done", zap.String("path", area.Path), zap.String("repoUrl", repoUrl))
}(ctx, repoUrl) }(ctx, repoUrl)
} }

View File

@ -38,8 +38,9 @@ func NewServerDeps(logger *zap.Logger) *ServerDeps {
} }
openPGPConfig := &signer.OpenPgpConfig{ openPGPConfig := &signer.OpenPgpConfig{
PrivateKeyFilePath: "./examples/private.pgp", PrivateKeyFilePath: "./example/testkey.private.pgp",
PrivateKeyPassword: "somepassword", PrivateKeyPassword: "somepassword",
PrivateKeyIdentity: "kraken@kasperhermansen.com",
} }
deps.openPGP = signer.NewOpenPGP(logger.With(zap.Namespace("openpgp")), openPGPConfig) deps.openPGP = signer.NewOpenPGP(logger.With(zap.Namespace("openpgp")), openPGPConfig)
@ -51,7 +52,7 @@ func (deps *ServerDeps) GetStorageService() *storage.Service {
} }
func (deps *ServerDeps) GetGitProvider() *providers.Git { func (deps *ServerDeps) GetGitProvider() *providers.Git {
return providers.NewGit(deps.logger.With(zap.Namespace("gitProvider")), deps.gitCfg) return providers.NewGit(deps.logger.With(zap.Namespace("gitProvider")), deps.gitCfg, deps.openPGP)
} }
func (deps *ServerDeps) GetAction() *actions.Action { func (deps *ServerDeps) GetAction() *actions.Action {

View File

@ -2,11 +2,14 @@ package providers
import ( import (
"context" "context"
"fmt"
"time" "time"
"git.front.kjuulh.io/kjuulh/kraken/internal/services/signer"
"git.front.kjuulh.io/kjuulh/kraken/internal/services/storage" "git.front.kjuulh.io/kjuulh/kraken/internal/services/storage"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object" "github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/transport" "github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/http" "github.com/go-git/go-git/v5/plumbing/transport/http"
@ -20,6 +23,7 @@ import (
type Git struct { type Git struct {
logger *zap.Logger logger *zap.Logger
gitConfig *GitConfig gitConfig *GitConfig
openPGP *signer.OpenPGP
} }
type GitRepo struct { type GitRepo struct {
@ -45,8 +49,8 @@ type GitConfig struct {
SshPrivateKeyPassword string SshPrivateKeyPassword string
} }
func NewGit(logger *zap.Logger, gitConfig *GitConfig) *Git { func NewGit(logger *zap.Logger, gitConfig *GitConfig, openPGP *signer.OpenPGP) *Git {
return &Git{logger: logger, gitConfig: gitConfig} return &Git{logger: logger, gitConfig: gitConfig, openPGP: openPGP}
} }
func (g *Git) Clone(ctx context.Context, storageArea *storage.Area, repoUrl string) (*GitRepo, error) { func (g *Git) Clone(ctx context.Context, storageArea *storage.Area, repoUrl string) (*GitRepo, error) {
@ -70,10 +74,7 @@ func (g *Git) Clone(ctx context.Context, storageArea *storage.Area, repoUrl stri
NoCheckout: false, NoCheckout: false,
Depth: 1, Depth: 1,
RecurseSubmodules: 1, RecurseSubmodules: 1,
Progress: &zapio.Writer{ Progress: g.getProgressWriter(),
Log: g.logger.With(zap.String("process", "go-git")),
Level: zap.DebugLevel,
},
Tags: 0, Tags: 0,
InsecureSkipTLS: false, InsecureSkipTLS: false,
CABundle: []byte{}, CABundle: []byte{},
@ -89,6 +90,13 @@ func (g *Git) Clone(ctx context.Context, storageArea *storage.Area, repoUrl stri
return &GitRepo{repo: repo}, nil return &GitRepo{repo: repo}, nil
} }
func (g *Git) getProgressWriter() *zapio.Writer {
return &zapio.Writer{
Log: g.logger.With(zap.String("process", "go-git")),
Level: zap.DebugLevel,
}
}
func (g *Git) Add(ctx context.Context, storageArea *storage.Area, gitRepo *GitRepo) (*git.Worktree, error) { func (g *Git) Add(ctx context.Context, storageArea *storage.Area, gitRepo *GitRepo) (*git.Worktree, error) {
worktree, err := gitRepo.repo.Worktree() worktree, err := gitRepo.repo.Worktree()
if err != nil { if err != nil {
@ -107,11 +115,71 @@ func (g *Git) Add(ctx context.Context, storageArea *storage.Area, gitRepo *GitRe
return nil, err return nil, err
} }
g.logger.Info("git status", zap.String("status", status.String())) g.logger.Debug("git status", zap.String("status", status.String()))
return worktree, nil return worktree, nil
} }
func (g *Git) CreateBranch(ctx context.Context, gitRepo *GitRepo) error {
worktree, err := gitRepo.repo.Worktree()
if err != nil {
return err
}
refSpec := plumbing.NewBranchReferenceName("kraken-apply")
err = gitRepo.repo.CreateBranch(&config.Branch{
Name: "kraken-apply",
Remote: "origin",
Merge: refSpec,
Rebase: "",
})
if err != nil {
return fmt.Errorf("could not create branch: %w", err)
}
err = worktree.Checkout(&git.CheckoutOptions{
Branch: plumbing.ReferenceName(refSpec.String()),
Create: true,
Force: false,
Keep: false,
})
if err != nil {
return fmt.Errorf("could not checkout branch: %w", err)
}
remoteRef := plumbing.NewRemoteReferenceName("origin", "kraken-apply")
ref := plumbing.NewSymbolicReference(refSpec, remoteRef)
err = gitRepo.repo.Storer.SetReference(ref)
if err != nil {
return fmt.Errorf("could not set reference: %w", err)
}
auth, err := g.GetAuth()
if err != nil {
return err
}
err = worktree.PullContext(ctx, &git.PullOptions{
RemoteName: "origin",
ReferenceName: "refs/heads/main",
SingleBranch: true,
Depth: 1,
Auth: auth,
RecurseSubmodules: 1,
Progress: g.getProgressWriter(),
Force: true,
InsecureSkipTLS: false,
CABundle: []byte{},
})
if err != nil {
return fmt.Errorf("could not pull from origin: %w", err)
}
g.logger.Debug("done creating branches")
return nil
}
func (g *Git) Commit(ctx context.Context, gitRepo *GitRepo) error { func (g *Git) Commit(ctx context.Context, gitRepo *GitRepo) error {
worktree, err := gitRepo.repo.Worktree() worktree, err := gitRepo.repo.Worktree()
if err != nil { if err != nil {
@ -122,12 +190,41 @@ func (g *Git) Commit(ctx context.Context, gitRepo *GitRepo) error {
All: true, All: true,
Author: &object.Signature{Name: "kraken", Email: "kraken@kasperhermansen.com", When: time.Now()}, Author: &object.Signature{Name: "kraken", Email: "kraken@kasperhermansen.com", When: time.Now()},
Committer: &object.Signature{Name: "kraken", Email: "kraken@kasperhermansen.com", When: time.Now()}, Committer: &object.Signature{Name: "kraken", Email: "kraken@kasperhermansen.com", When: time.Now()},
SignKey: &openpgp.Entity{}, SignKey: g.openPGP.SigningKey,
}) })
if err != nil { if err != nil {
return err return err
} }
g.logger.Debug("done commiting objects")
return nil
}
func (g *Git) Push(ctx context.Context, gitRepo *GitRepo) error {
auth, err := g.GetAuth()
if err != nil {
return err
}
err = gitRepo.repo.PushContext(ctx, &git.PushOptions{
RemoteName: "origin",
RefSpecs: []config.RefSpec{},
Auth: auth,
Progress: g.getProgressWriter(),
Prune: false,
Force: false,
InsecureSkipTLS: false,
CABundle: []byte{},
RequireRemoteRefs: []config.RefSpec{},
})
if err != nil {
return err
}
g.logger.Debug("done pushing branch")
return nil return nil
} }

View File

@ -2,22 +2,25 @@ package signer
import ( import (
"context" "context"
"errors"
"os" "os"
"strings"
"git.front.kjuulh.io/kjuulh/curre" "git.front.kjuulh.io/kjuulh/curre"
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/go-crypto/openpgp"
"go.uber.org/zap" "go.uber.org/zap"
) )
type OpenPGP struct { type OpenPGP struct {
logger *zap.Logger logger *zap.Logger
PrivateKeyRing *crypto.KeyRing SigningKey *openpgp.Entity
config *OpenPgpConfig config *OpenPgpConfig
} }
type OpenPgpConfig struct { type OpenPgpConfig struct {
PrivateKeyFilePath string PrivateKeyFilePath string
PrivateKeyPassword string PrivateKeyPassword string
PrivateKeyIdentity string
} }
func NewOpenPGP(logger *zap.Logger, config *OpenPgpConfig) *OpenPGP { func NewOpenPGP(logger *zap.Logger, config *OpenPgpConfig) *OpenPGP {
@ -29,26 +32,14 @@ func NewOpenPGP(logger *zap.Logger, config *OpenPgpConfig) *OpenPGP {
func NewOpenPGPApp(openPGP *OpenPGP) curre.Component { func NewOpenPGPApp(openPGP *OpenPGP) curre.Component {
return curre.NewFunctionalComponent(&curre.FunctionalComponent{ return curre.NewFunctionalComponent(&curre.FunctionalComponent{
InitFunc: func(fc *curre.FunctionalComponent, ctx context.Context) error { InitFunc: func(_ *curre.FunctionalComponent, ctx context.Context) error {
keyring, err := buildKeyring(ctx, openPGP)
content, err := os.ReadFile(openPGP.config.PrivateKeyFilePath)
if err != nil {
return err
}
privateKeyObj, err := crypto.NewKeyFromArmored(string(content))
if err != nil {
return err
}
unlockedPrivateKeyRing, err := privateKeyObj.Unlock([]byte(openPGP.config.PrivateKeyPassword))
if err != nil {
return err
}
privateKeyRing, err := crypto.NewKeyRing(unlockedPrivateKeyRing)
if err != nil { if err != nil {
openPGP.logger.Panic("could not build keyring", zap.Error(err))
return err return err
} }
openPGP.PrivateKeyRing = privateKeyRing openPGP.SigningKey = keyring
return nil return nil
}, },
@ -59,5 +50,32 @@ func NewOpenPGPApp(openPGP *OpenPGP) curre.Component {
return nil return nil
}, },
}) })
}
func buildKeyring(_ context.Context, openPGP *OpenPGP) (*openpgp.Entity, error) {
content, err := os.ReadFile(openPGP.config.PrivateKeyFilePath)
if err != nil {
return nil, err
}
reader := strings.NewReader(string(content))
es, err := openpgp.ReadArmoredKeyRing(reader)
if err != nil {
return nil, err
}
for _, key := range es {
for k := range key.Identities {
if strings.Contains(k, openPGP.config.PrivateKeyIdentity) {
err = key.PrivateKey.Decrypt([]byte(openPGP.config.PrivateKeyPassword))
if err != nil {
return nil, err
}
return key, nil
}
}
}
return nil, errors.New("could not find key matching identity")
} }