Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions internal/git/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,14 @@ func (m *managerImpl) CloneRepository(ctx context.Context, repoUrl, subPath, ref
return nil, fmt.Errorf("failed to create temporary directory: %w", err)
}

clientOpts, tempFile := m.getClientOptions(parsedURL.Scheme, auth)

repo, err := git.PlainCloneContext(ctx, targetDir, &git.CloneOptions{
URL: repoUrl,
ReferenceName: plumbing.ReferenceName(reference),
SingleBranch: true,
Depth: 1,
ClientOptions: m.getClientOptions(parsedURL.Scheme, auth),
ClientOptions: clientOpts,
})
if err != nil {
return nil, fmt.Errorf("failed to clone repo: %w", err)
Expand All @@ -70,19 +72,22 @@ func (m *managerImpl) CloneRepository(ctx context.Context, repoUrl, subPath, ref
return nil, fmt.Errorf("failed to find head: %w", err)
}

return &Repository{
result := &Repository{
CloneDir: targetDir,
SubPath: subPath,
Commit: head.Hash().String(),
Branch: reference,
}, nil
}
result.AddTempFile(tempFile)

return result, nil
}

func (m *managerImpl) getClientOptions(scheme string, authSecret map[string][]byte) []client.Option {
func (m *managerImpl) getClientOptions(scheme string, authSecret map[string][]byte) ([]client.Option, string) {
if scheme == "ssh" {
return m.getSSHClientOptions(authSecret)
}
return m.getHTTPClientOptions(authSecret)
return m.getHTTPClientOptions(authSecret), ""
}

func (m *managerImpl) getHTTPClientOptions(authSecret map[string][]byte) []client.Option {
Expand Down Expand Up @@ -125,37 +130,38 @@ func ensureKnownHostsExists() error {
return nil
}

func (m *managerImpl) getSSHClientOptions(authSecret map[string][]byte) []client.Option {
func (m *managerImpl) getSSHClientOptions(authSecret map[string][]byte) ([]client.Option, string) {
privateKey, hasKey := authSecret["sshPrivateKey"]
if !hasKey {
return []client.Option{
client.WithSSHAuth(&gitssh.Password{
User: "git",
HostKeyCallbackHelper: gitssh.HostKeyCallbackHelper{HostKeyCallback: gossh.InsecureIgnoreHostKey()},
}),
}
}, ""
}

password := string(authSecret["sshPrivateKeyPassword"])
auth, err := gitssh.NewPublicKeys("git", privateKey, password)
if err != nil {
return nil
return nil, ""
}
auth.HostKeyCallback = gossh.InsecureIgnoreHostKey()

var tempFilePath string
if knownHostsData, ok := authSecret["known_hosts"]; ok {
tmpFile, err := os.CreateTemp("", "known_hosts-*")
if err == nil {
defer os.Remove(tmpFile.Name())
if _, err := tmpFile.Write(knownHostsData); err == nil {
_ = tmpFile.Close()
cb, err := gitssh.NewKnownHostsCallback(tmpFile.Name())
tempFilePath = tmpFile.Name()
cb, err := gitssh.NewKnownHostsCallback(tempFilePath)
if err == nil {
auth.HostKeyCallback = cb
}
}
}
}

return []client.Option{client.WithSSHAuth(auth)}
return []client.Option{client.WithSSHAuth(auth)}, tempFilePath
}
17 changes: 10 additions & 7 deletions internal/git/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,40 +20,43 @@ JtdGRlLmNzYgECAw==
func TestGetClientOptions_HTTPToken(t *testing.T) {
m := &managerImpl{}
secret := map[string][]byte{"token": []byte("my-token")}
opts := m.getClientOptions("https", secret)
opts, tmpFile := m.getClientOptions("https", secret)
if len(opts) != 1 {
t.Fatalf("expected 1 option, got %d", len(opts))
}
if tmpFile != "" {
t.Fatalf("expected no temp file, got %s", tmpFile)
}
}

func TestGetClientOptions_HTTPUsernamePassword(t *testing.T) {
m := &managerImpl{}
secret := map[string][]byte{"username": []byte("user"), "password": []byte("pass")}
opts := m.getClientOptions("http", secret)
opts, _ := m.getClientOptions("http", secret)
if len(opts) != 1 {
t.Fatalf("expected 1 option, got %d", len(opts))
}
}

func TestGetClientOptions_HTTPEmpty(t *testing.T) {
m := &managerImpl{}
opts := m.getClientOptions("https", nil)
opts, _ := m.getClientOptions("https", nil)
if opts != nil {
t.Fatalf("expected nil options, got %v", opts)
}
}

func TestGetClientOptions_SSHNoSecret(t *testing.T) {
m := &managerImpl{}
opts := m.getClientOptions(sshScheme, nil)
opts, _ := m.getClientOptions(sshScheme, nil)
if len(opts) != 1 {
t.Fatalf("expected 1 option for insecure SSH, got %d", len(opts))
}
}

func TestGetClientOptions_SSHEmptySecret(t *testing.T) {
m := &managerImpl{}
opts := m.getClientOptions(sshScheme, map[string][]byte{})
opts, _ := m.getClientOptions(sshScheme, map[string][]byte{})
if len(opts) != 1 {
t.Fatalf("expected 1 option for insecure SSH, got %d", len(opts))
}
Expand All @@ -62,7 +65,7 @@ func TestGetClientOptions_SSHEmptySecret(t *testing.T) {
func TestGetClientOptions_SSHWithPrivateKey(t *testing.T) {
m := &managerImpl{}
secret := map[string][]byte{"sshPrivateKey": []byte(testEd25519PrivateKey)}
opts := m.getClientOptions(sshScheme, secret)
opts, _ := m.getClientOptions(sshScheme, secret)
if len(opts) != 1 {
t.Fatalf("expected 1 option, got %d", len(opts))
}
Expand All @@ -71,7 +74,7 @@ func TestGetClientOptions_SSHWithPrivateKey(t *testing.T) {
func TestGetClientOptions_SSHWithInvalidKey(t *testing.T) {
m := &managerImpl{}
secret := map[string][]byte{"sshPrivateKey": []byte("not-a-valid-key")}
opts := m.getClientOptions(sshScheme, secret)
opts, _ := m.getClientOptions(sshScheme, secret)
if opts != nil {
t.Fatalf("expected nil options for invalid key, got %v", opts)
}
Expand Down
18 changes: 14 additions & 4 deletions internal/git/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,26 @@
)

type Repository struct {
CloneDir string
SubPath string
Commit string
Branch string
CloneDir string
SubPath string
Commit string
Branch string
tempFiles []string
}

func (r *Repository) AddTempFile(path string) {

Check failure on line 16 in internal/git/repository.go

View workflow job for this annotation

GitHub Actions / Lint

import-shadowing: The name 'path' shadows an import name (revive)
if path != "" {
r.tempFiles = append(r.tempFiles, path)
}
}

func (r *Repository) Path() string {
return path.Join(r.CloneDir, r.SubPath)
}

func (r *Repository) Cleanup() error {
for _, f := range r.tempFiles {
os.Remove(f)

Check failure on line 28 in internal/git/repository.go

View workflow job for this annotation

GitHub Actions / Lint

Error return value of `os.Remove` is not checked (errcheck)
}
return os.RemoveAll(r.CloneDir)
}
Loading