diff --git a/models/repo/mirror_ssh_keypair_test.go b/models/repo/mirror_ssh_keypair_test.go index 383550948e..f09b8b5d1b 100644 --- a/models/repo/mirror_ssh_keypair_test.go +++ b/models/repo/mirror_ssh_keypair_test.go @@ -4,7 +4,6 @@ package repo_test import ( - "context" "crypto/ed25519" "testing" @@ -29,8 +28,8 @@ func TestMirrorSSHKeypair(t *testing.T) { assert.NotEmpty(t, keypair.PublicKey) assert.NotEmpty(t, keypair.PrivateKeyEncrypted) assert.NotEmpty(t, keypair.Fingerprint) - assert.True(t, keypair.CreatedUnix > 0) - assert.True(t, keypair.UpdatedUnix > 0) + assert.Positive(t, keypair.CreatedUnix) + assert.Positive(t, keypair.UpdatedUnix) // Verify the public key is in SSH format assert.Contains(t, keypair.PublicKey, "ssh-ed25519") @@ -77,11 +76,11 @@ func TestMirrorSSHKeypair(t *testing.T) { privateKey, err := keypair.GetDecryptedPrivateKey() require.NoError(t, err) assert.IsType(t, ed25519.PrivateKey{}, privateKey) - assert.Equal(t, ed25519.PrivateKeySize, len(privateKey)) + assert.Len(t, privateKey, ed25519.PrivateKeySize) // Verify the private key corresponds to the public key publicKey := privateKey.Public().(ed25519.PublicKey) - assert.Equal(t, ed25519.PublicKeySize, len(publicKey)) + assert.Len(t, publicKey, ed25519.PublicKeySize) }) t.Run("DeleteMirrorSSHKeypair", func(t *testing.T) { @@ -128,7 +127,7 @@ func TestMirrorSSHKeypairConcurrency(t *testing.T) { // Test concurrent creation of keypairs to ensure no race conditions t.Run("ConcurrentCreation", func(t *testing.T) { - ctx := context.Background() + ctx := t.Context() results := make(chan error, 10) // Start multiple goroutines creating keypairs for different owners diff --git a/modules/git/remote.go b/modules/git/remote.go index 5db3db71a5..a36b106827 100644 --- a/modules/git/remote.go +++ b/modules/git/remote.go @@ -5,6 +5,7 @@ package git import ( "context" + "errors" "fmt" "net/url" "strings" @@ -91,33 +92,33 @@ func IsRemoteNotExistError(err error) bool { // normalizeSSHURL converts SSH-SCP format URLs to standard ssh:// format for security func normalizeSSHURL(remoteAddr string) (string, error) { if strings.Contains(remoteAddr, "://") { - return remoteAddr, fmt.Errorf("remoteAddr has a scheme") + return remoteAddr, errors.New("remoteAddr has a scheme") } if strings.Contains(remoteAddr, "\\") { - return remoteAddr, fmt.Errorf("remoteAddr has Windows path slashes") + return remoteAddr, errors.New("remoteAddr has Windows path slashes") } if strings.Contains(remoteAddr, ":/") { - return remoteAddr, fmt.Errorf("remoteAddr could be Windows drive with forward slash") + return remoteAddr, errors.New("remoteAddr could be Windows drive with forward slash") } if remoteAddr != "" && (remoteAddr[0] == '/' || remoteAddr[0] == '\\') { - return remoteAddr, fmt.Errorf("remoteAddr is a local file path") + return remoteAddr, errors.New("remoteAddr is a local file path") } // Parse SSH-SCP format: [user@]host:path colonIndex := strings.Index(remoteAddr, ":") if colonIndex == -1 { - return remoteAddr, fmt.Errorf("remoteAddr has no colon") + return remoteAddr, errors.New("remoteAddr has no colon") } if colonIndex == 1 && len(remoteAddr) > 2 { - return remoteAddr, fmt.Errorf("remoteAddr could be Windows drive letter check (C:, D:, etc.)") + return remoteAddr, errors.New("remoteAddr could be Windows drive letter check (C:, D:, etc.)") } hostPart := remoteAddr[:colonIndex] pathPart := remoteAddr[colonIndex+1:] if hostPart == "" || pathPart == "" { - return remoteAddr, fmt.Errorf("remoteAddr has empty host or path") + return remoteAddr, errors.New("remoteAddr has empty host or path") } var user, host string @@ -130,7 +131,7 @@ func normalizeSSHURL(remoteAddr string) (string, error) { } if host == "" { - return remoteAddr, fmt.Errorf("Must have SSH host") + return remoteAddr, errors.New("Must have SSH host") } return fmt.Sprintf("ssh://%s%s/%s", user, host, pathPart), nil diff --git a/modules/ssh/agent.go b/modules/ssh/agent.go index 0fd7725011..d6b6a9c674 100644 --- a/modules/ssh/agent.go +++ b/modules/ssh/agent.go @@ -20,8 +20,8 @@ import ( "golang.org/x/crypto/ssh/agent" ) -// SSHAgent represents a temporary SSH agent for repo mirroring -type SSHAgent struct { +// Agent represents a temporary SSH agent for repo mirroring +type Agent struct { socketPath string listener net.Listener agent agent.Agent @@ -32,7 +32,7 @@ type SSHAgent struct { } // NewSSHAgent creates a new SSH agent with the given private key -func NewSSHAgent(privateKey ed25519.PrivateKey) (*SSHAgent, error) { +func NewSSHAgent(privateKey ed25519.PrivateKey) (*Agent, error) { var listener net.Listener var socketPath string var tempDir string @@ -108,7 +108,7 @@ func NewSSHAgent(privateKey ed25519.PrivateKey) (*SSHAgent, error) { } // Create our SSH agent wrapper - sa := &SSHAgent{ + sa := &Agent{ socketPath: socketPath, listener: listener, agent: sshAgent, @@ -126,7 +126,7 @@ func NewSSHAgent(privateKey ed25519.PrivateKey) (*SSHAgent, error) { } // serve handles incoming connections to the SSH agent -func (sa *SSHAgent) serve() { +func (sa *Agent) serve() { defer sa.wg.Done() defer sa.cleanup() @@ -139,7 +139,9 @@ func (sa *SSHAgent) serve() { if runtime.GOOS != "windows" { // On Windows, named pipes don't support SetDeadline in the same way if listener, ok := sa.listener.(*net.UnixListener); ok { - listener.SetDeadline(time.Now().Add(100 * time.Millisecond)) + if err := listener.SetDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { + log.Debug("Failed to set listener deadline: %v", err) + } } } @@ -172,7 +174,7 @@ func (sa *SSHAgent) serve() { } // cleanup removes the socket file and temporary directory -func (sa *SSHAgent) cleanup() { +func (sa *Agent) cleanup() { if sa.socketPath != "" { if runtime.GOOS != "windows" { // On Windows, named pipes are automatically cleaned up when closed @@ -184,12 +186,12 @@ func (sa *SSHAgent) cleanup() { } // GetSocketPath returns the path to the SSH agent socket -func (sa *SSHAgent) GetSocketPath() string { +func (sa *Agent) GetSocketPath() string { return sa.socketPath } // Close stops the SSH agent and cleans up resources -func (sa *SSHAgent) Close() error { +func (sa *Agent) Close() error { sa.mu.Lock() defer sa.mu.Unlock() @@ -209,14 +211,14 @@ func (sa *SSHAgent) Close() error { return nil } -// SSHAgentManager manages temporary SSH agents for git operations -type SSHAgentManager struct { +// AgentManager manages temporary SSH agents for git operations +type AgentManager struct { mu sync.Mutex - agents map[string]*SSHAgent + agents map[string]*Agent } -var globalAgentManager = &SSHAgentManager{ - agents: make(map[string]*SSHAgent), +var globalAgentManager = &AgentManager{ + agents: make(map[string]*Agent), } // CreateTemporaryAgent creates a temporary SSH agent with the given private key