Skip to content

[sftp] add support#8

Draft
capcom6 wants to merge 4 commits into
masterfrom
sftp/add-support
Draft

[sftp] add support#8
capcom6 wants to merge 4 commits into
masterfrom
sftp/add-support

Conversation

@capcom6
Copy link
Copy Markdown
Owner

@capcom6 capcom6 commented May 18, 2026

Summary by CodeRabbit

  • New Features

    • Added SFTP support for remote sync with multiple auth modes (password, SSH key, passphrase, SSH agent) and sftp:// URL handling.
  • Documentation

    • README and CLI help updated with FTP/SFTP usage examples, destination URL formats, auth query params, default ports, and roadmap status.
  • Tests

    • Added unit tests for FTP and SFTP URL path handling.
  • Chores

    • Bumped Go version and updated linter configuration.

Review Change Stack

Comment thread internal/client/sftp/sftp.go Fixed
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 18, 2026

🤖 Pull request artifacts

Platform File
🐳 Docker GitHub Container Registry
🍎 Darwin arm64 sftp-sync_Darwin_arm64.tar.gz
🍎 Darwin x86_64 sftp-sync_Darwin_x86_64.tar.gz
🐧 Linux arm64 sftp-sync_Linux_arm64.tar.gz
🐧 Linux i386 sftp-sync_Linux_i386.tar.gz
🐧 Linux x86_64 sftp-sync_Linux_x86_64.tar.gz
🪟 Windows arm64 sftp-sync_Windows_arm64.zip
🪟 Windows i386 sftp-sync_Windows_i386.zip
🪟 Windows x86_64 sftp-sync_Windows_x86_64.zip

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1f3def8a-dd67-45cc-ac64-34058f11298c

📥 Commits

Reviewing files that changed from the base of the PR and between 2a50167 and 6fc36ca.

📒 Files selected for processing (1)
  • internal/client/ftp/ftp.go

Walkthrough

This PR implements SFTP protocol support alongside existing FTP: adds a new SFTP client and auth helpers, refactors the FTP client into an ftp package, routes client construction by URL scheme, updates docs/CLI, bumps Go/deps, and adds URL-path tests.

Changes

SFTP protocol support

Layer / File(s) Summary
Shared error types foundation
internal/client/types/errors.go
Error definitions moved to internal/client/types; ErrInvalidParams and ErrInvalidPath added.
Dependency and tooling updates
go.mod, .golangci.yml
go 1.25.0; golang.org/x/crypto and indirects bumped; github.com/kr/fs added; .golangci.yml excludes golang.org/x/crypto/ssh.*Config from exhaustruct.
Documentation and CLI updates
README.md, main.go, internal/cli/commands/sync/sync.go
README and CLI help updated to advertise FTP or SFTP, include SFTP usage/auth examples and port notes, and mark SFTP support complete.
Client factory scheme routing
internal/client/client.go
New routes ftp://ftp.NewClient and sftp://sftp.NewClient; unsupported schemes return an error wrapping types.ErrUnsupportedScheme.
FTP client refactoring for package structure
internal/client/ftp/ftp.go
FTP client moved to ftp package; type renamed to Client, constructor NewClient, receivers updated, URL path ChangeDir handled, and errors reuse types.
SFTP auth helpers
internal/client/sftp/auth.go
Adds AuthConfig, ParseAuthFromURL, BuildAuthMethods, SSH agent/private-key/password resolution, passphrase handling, default-key discovery, tilde expansion, and sentinel auth errors.
SFTP config parsing
internal/client/sftp/config.go
Parses host/port/username and wires AuthConfig; defaults port to 22.
SFTP client implementation
internal/client/sftp/sftp.go
New SFTP client with lazy SSH/SFTP init, known_hosts support, basePath/resolvePath, ping, MakeDir, recursive RemoveDir, UploadFile, RemoveFile, Remove dispatch, ignorable-error logic, and splitPath helper.
Tests for URL parsing and validation
internal/client/ftp/ftp_test.go, internal/client/sftp/sftp_test.go
Adds table-driven, parallel tests verifying URL path extraction and SFTP path handling.

Sequence Diagram

sequenceDiagram
  participant Caller
  participant ClientFactory as internal/client.New
  participant FtpFactory as ftp.NewClient
  participant SftpFactory as sftp.NewClient
  participant SSH as ssh.Dial
  Caller->>ClientFactory: New(address, logger)
  alt URL scheme is "ftp"
    ClientFactory->>FtpFactory: ftp.NewClient(url, logger)
    FtpFactory-->>ClientFactory: *ftp.Client
  else URL scheme is "sftp"
    ClientFactory->>SftpFactory: sftp.NewClient(url, logger)
    SftpFactory->>SSH: Dial SSH (host, auth)
    SSH-->>SftpFactory: ssh.Client
    SftpFactory-->>ClientFactory: *sftp.Client
  else unsupported scheme
    ClientFactory-->>Caller: error(types.ErrUnsupportedScheme)
  end
  ClientFactory-->>Caller: Client, error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • capcom6/sftp-sync#5: Prior PR touching the client.New factory and sync command help; overlaps with factory/CLI areas.

Suggested labels

codex

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title '[sftp] add support' is vague and generic, using non-descriptive terms that don't clearly convey what support is being added or the main scope of changes. Revise the title to be more specific and descriptive, e.g., 'Add SFTP protocol support' or 'Add SFTP client implementation with multiple auth methods', to clearly indicate the primary change.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sftp/add-support

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

77-82: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update About section to include SFTP support.

Line 81 still says “remote FTP server,” which conflicts with the updated FTP+SFTP positioning in the rest of the README.

Suggested patch
-sftp-sync is a command-line utility for syncing a local folder with a remote FTP server on every change of files or directories.
+sftp-sync is a command-line utility for syncing a local folder with a remote FTP or SFTP server on every change of files or directories.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 77 - 82, The About section still calls out "remote
FTP server"; update the text under "About The Project" (the sftp-sync project
description) to reflect SFTP support by replacing that phrase with a combined
term such as "remote FTP or SFTP server" or "remote FTP/SFTP server" so it
matches the README's FTP+SFTP positioning.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/client/sftp/sftp.go`:
- Around line 70-72: The current parsing in sftp.go that checks if
strings.Contains(host, ":") and then does strings.Cut(host, ":") incorrectly
splits IPv6 addresses; replace that logic by using the URL object's helpers:
call u.Hostname() to get the host (with IPv6 brackets removed) and u.Port() to
get the port string (or blank if none) and assign to the existing host and port
variables (fall back to default port if u.Port() is empty). Update references
around variables named host, port and the URL variable u to use these methods
rather than manual string slicing.
- Around line 159-166: The recursive delete in removeDirRecur is listing the
parent directory because it calls c.sftp.ReadDirContext(ctx, path.Dir(p))
instead of the target path; update the ReadDirContext call in
Client.removeDirRecur to use p (the directory being removed) so entries are read
from the correct directory, and ensure any subsequent path joins or recursive
calls (inside removeDirRecur) continue to operate on p and its child paths
rather than path.Dir(p).
- Line 82: Replace the insecure HostKeyCallback currently set to
ssh.InsecureIgnoreHostKey() in the SSH client configuration with a known-hosts
based callback using knownhosts.New. Import golang.org/x/crypto/ssh/knownhosts
and build the known_hosts path (e.g., filepath.Join(os.UserHomeDir(), ".ssh",
"known_hosts")), call knownhosts.New(...) to get the callback, handle any error
(return or log) from knownhosts.New, and set the config's HostKeyCallback to the
returned callback instead of ssh.InsecureIgnoreHostKey(); update imports to
include os and path/filepath as needed.
- Around line 274-279: Update the error-matching logic around the notFoundErrors
slice: remove the overly broad "failure" entry and the case-sensitive "No such
file", normalize the error string with strings.ToLower(err.Error()) before
comparing, and additionally check os.IsNotExist(err) to reliably detect
file-not-found cases; i.e., keep only specific patterns like "does not exist",
"not found", "no such file" in notFoundErrors, use strings.ToLower when scanning
those patterns, and short-circuit to treat the error as a not-found only if
strings match or os.IsNotExist(err) returns true (do not suppress permission or
connection errors).

---

Outside diff comments:
In `@README.md`:
- Around line 77-82: The About section still calls out "remote FTP server";
update the text under "About The Project" (the sftp-sync project description) to
reflect SFTP support by replacing that phrase with a combined term such as
"remote FTP or SFTP server" or "remote FTP/SFTP server" so it matches the
README's FTP+SFTP positioning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a61725ef-8cc6-495c-be81-e98004aebbec

📥 Commits

Reviewing files that changed from the base of the PR and between 5131d20 and 39cc868.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (9)
  • .golangci.yml
  • README.md
  • go.mod
  • internal/cli/commands/sync/sync.go
  • internal/client/client.go
  • internal/client/ftp/ftp.go
  • internal/client/sftp/sftp.go
  • internal/client/types/errors.go
  • main.go

Comment thread internal/client/sftp/sftp.go Outdated
Comment thread internal/client/sftp/sftp.go Outdated
Comment thread internal/client/sftp/sftp.go
Comment thread internal/client/sftp/sftp.go
@capcom6 capcom6 force-pushed the sftp/add-support branch from 43e2de0 to 0b6f0ea Compare May 19, 2026 01:21
@capcom6 capcom6 force-pushed the sftp/add-support branch from 533b055 to bb43881 Compare May 20, 2026 07:22
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/client/ftp/ftp.go (1)

76-83: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Close and discard partially initialized FTP sessions on setup failure.

If Login or ChangeDir fails, the new connection remains assigned to c.client. A later init() can pass ping() and skip setup, causing operations to run in the wrong remote directory.

Suggested fix
-	c.client, err = ftp.Dial(u.Host, ftp.DialWithContext(ctx))
+	conn, err := ftp.Dial(u.Host, ftp.DialWithContext(ctx))
 	if err != nil {
 		return fmt.Errorf("can't connect to %s: %w", u.Host, err)
 	}
@@
-	if loginErr := c.client.Login(u.User.Username(), password); loginErr != nil {
+	if loginErr := conn.Login(u.User.Username(), password); loginErr != nil {
+		_ = conn.Quit()
 		return fmt.Errorf("can't login as %s: %w", u.User.Username(), loginErr)
 	}
 
 	if u.Path != "" && u.Path != "/" {
-		if chErr := c.client.ChangeDir(u.Path); chErr != nil {
+		if chErr := conn.ChangeDir(u.Path); chErr != nil {
+			_ = conn.Quit()
 			return fmt.Errorf("remote path %s does not exist or is not accessible: %w", u.Path, chErr)
 		}
 	}
+
+	c.client = conn
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/client/ftp/ftp.go` around lines 76 - 83, When setup fails during ftp
session initialization (calls to c.client.Login or c.client.ChangeDir), ensure
the partially-initialized c.client is closed and discarded so subsequent
init()/ping() do not reuse it; on both the Login failure branch and the
ChangeDir failure branch call c.client.Close() (handle/ignore Close() error as
appropriate) and then set c.client = nil before returning the wrapped error from
Login or ChangeDir, so the client state is cleaned up on setup failure.
🧹 Nitpick comments (3)
internal/client/sftp/sftp_test.go (1)

49-69: ⚡ Quick win

Test currently validates duplicated logic, not implementation behavior.

TestURLPathValidationRules re-derives the rule inline, so it won’t catch regressions in the actual SFTP path-handling code. Please assert this through the real path-validation/dir-selection behavior (or a helper used by production code) instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/client/sftp/sftp_test.go` around lines 49 - 69, The test is
re-deriving the path rule instead of exercising the real code; update
TestURLPathValidationRules to call the actual production path-validation or
dir-selection code (replace the inline computation `shouldUse := tt.path != ""
&& tt.path != "/"` in TestURLPathValidationRules with a call to the
helper/function used by the SFTP client to decide whether to change directories)
and assert that its return matches tt.shouldUse; if the decision is encapsulated
in a method on the SFTP client, construct the minimal client or invoke the
exported helper so the test validates implementation behavior rather than
duplicated logic.
internal/client/sftp/sftp.go (2)

92-96: 💤 Low value

Consider adding a connection timeout.

The SSH ClientConfig lacks a Timeout field. While OS-level TCP timeouts exist, an explicit timeout provides predictable behavior and prevents indefinite hangs against unresponsive servers.

♻️ Proposed fix
 	config := &ssh.ClientConfig{
 		User:            username,
 		Auth:            authMethods,
 		HostKeyCallback: hostKeyCallback,
+		Timeout:         30 * time.Second,
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/client/sftp/sftp.go` around lines 92 - 96, The ssh.ClientConfig
named config currently has no connection timeout; to avoid hangs, implement a
TCP-level timeout by creating a net.Dialer with a reasonable Timeout and use
dialer.Dial to open the TCP connection and then wrap it with ssh.NewClientConn
and ssh.NewClient (instead of calling ssh.Dial). Update the code path that uses
config (the SFTP connection setup / connect function where config is passed) to
use this dialer-based flow so the SSH handshake respects the configured timeout.

81-84: ⚡ Quick win

Use os.UserHomeDir() for cross-platform compatibility.

os.Getenv("HOME") doesn't work on Windows and may be empty in some environments. os.UserHomeDir() handles platform differences correctly.

♻️ Proposed fix
-	hostKeyCallback, err := knownhosts.New(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
+	home, err := os.UserHomeDir()
+	if err != nil {
+		return fmt.Errorf("can't determine home directory: %w", err)
+	}
+	hostKeyCallback, err := knownhosts.New(filepath.Join(home, ".ssh", "known_hosts"))
 	if err != nil {
 		return fmt.Errorf("can't load known_hosts: %w", err)
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/client/sftp/sftp.go` around lines 81 - 84, Replace the use of
os.Getenv("HOME") when building the known_hosts path with os.UserHomeDir() and
handle its error: call os.UserHomeDir(), check for an error, then use
filepath.Join(userHome, ".ssh", "known_hosts") when calling knownhosts.New (the
hostKeyCallback initialization). Ensure any error from os.UserHomeDir() is
returned (similar to the existing error handling around knownhosts.New) so the
function fails cleanly if the home directory can't be resolved.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/client/sftp/auth.go`:
- Around line 84-100: The buildAgentSigners function leaks the agent socket
connection because conn is never closed; after successfully dialing the SSH
agent in buildAgentSigners (the conn returned by dialer.DialContext) defer
conn.Close() immediately (or otherwise close conn before each return) so the
file descriptor is released; ensure both the success path (after agent.NewClient
and Signers()) and the error paths close the connection by placing the defer
right after the dial succeeds.

---

Outside diff comments:
In `@internal/client/ftp/ftp.go`:
- Around line 76-83: When setup fails during ftp session initialization (calls
to c.client.Login or c.client.ChangeDir), ensure the partially-initialized
c.client is closed and discarded so subsequent init()/ping() do not reuse it; on
both the Login failure branch and the ChangeDir failure branch call
c.client.Close() (handle/ignore Close() error as appropriate) and then set
c.client = nil before returning the wrapped error from Login or ChangeDir, so
the client state is cleaned up on setup failure.

---

Nitpick comments:
In `@internal/client/sftp/sftp_test.go`:
- Around line 49-69: The test is re-deriving the path rule instead of exercising
the real code; update TestURLPathValidationRules to call the actual production
path-validation or dir-selection code (replace the inline computation `shouldUse
:= tt.path != "" && tt.path != "/"` in TestURLPathValidationRules with a call to
the helper/function used by the SFTP client to decide whether to change
directories) and assert that its return matches tt.shouldUse; if the decision is
encapsulated in a method on the SFTP client, construct the minimal client or
invoke the exported helper so the test validates implementation behavior rather
than duplicated logic.

In `@internal/client/sftp/sftp.go`:
- Around line 92-96: The ssh.ClientConfig named config currently has no
connection timeout; to avoid hangs, implement a TCP-level timeout by creating a
net.Dialer with a reasonable Timeout and use dialer.Dial to open the TCP
connection and then wrap it with ssh.NewClientConn and ssh.NewClient (instead of
calling ssh.Dial). Update the code path that uses config (the SFTP connection
setup / connect function where config is passed) to use this dialer-based flow
so the SSH handshake respects the configured timeout.
- Around line 81-84: Replace the use of os.Getenv("HOME") when building the
known_hosts path with os.UserHomeDir() and handle its error: call
os.UserHomeDir(), check for an error, then use filepath.Join(userHome, ".ssh",
"known_hosts") when calling knownhosts.New (the hostKeyCallback initialization).
Ensure any error from os.UserHomeDir() is returned (similar to the existing
error handling around knownhosts.New) so the function fails cleanly if the home
directory can't be resolved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a065f693-732f-40b6-a4dd-d0c5dc4050b2

📥 Commits

Reviewing files that changed from the base of the PR and between 0b6f0ea and bb43881.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (12)
  • .golangci.yml
  • README.md
  • go.mod
  • internal/cli/commands/sync/sync.go
  • internal/client/client.go
  • internal/client/ftp/ftp.go
  • internal/client/ftp/ftp_test.go
  • internal/client/sftp/auth.go
  • internal/client/sftp/sftp.go
  • internal/client/sftp/sftp_test.go
  • internal/client/types/errors.go
  • main.go
✅ Files skipped from review due to trivial changes (4)
  • go.mod
  • internal/cli/commands/sync/sync.go
  • .golangci.yml
  • README.md

Comment thread internal/client/sftp/auth.go
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/client/ftp/ftp.go (1)

71-78: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Guard u.User before calling Password() / Username() in FTP login to avoid nil panic.

internal/client/ftp/ftp.go dereferences u.User.Password() and u.User.Username() (for conn.Login and error formatting) without any u.User == nil guard; a URL without userinfo (e.g., ftp://host/path) can therefore panic during connection initialization. Add a validation check and return an invalid-params error consistent with existing error handling in this package.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/client/ftp/ftp.go` around lines 71 - 78, Guard against a nil User
before calling Password() and Username(): check if u.User == nil at the start of
the FTP login sequence in internal/client/ftp/ftp.go and return the package's
standard "invalid-params" error (consistent with existing error handling)
instead of proceeding; then use local username/password variables (from
u.User.Username() and u.User.Password()) when calling conn.Login and when
formatting the login error so no nil dereference can occur during conn.Login or
the error path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/client/sftp/sftp.go`:
- Around line 83-97: Before constructing ssh.ClientConfig and calling ssh.Dial,
validate that ParseConfigFromURL returned non-empty config.Host and
config.Username and return types.ErrInvalidParams if either is empty;
specifically, check config.Host and config.Username (derived by
ParseConfigFromURL from u.Hostname() and u.User.Username()), and only proceed to
build ssh.ClientConfig and call ssh.Dial(net.JoinHostPort(config.Host,
config.Port), sshConfig) when both are present — otherwise return
types.ErrInvalidParams to fail fast on malformed SFTP URLs.

---

Outside diff comments:
In `@internal/client/ftp/ftp.go`:
- Around line 71-78: Guard against a nil User before calling Password() and
Username(): check if u.User == nil at the start of the FTP login sequence in
internal/client/ftp/ftp.go and return the package's standard "invalid-params"
error (consistent with existing error handling) instead of proceeding; then use
local username/password variables (from u.User.Username() and u.User.Password())
when calling conn.Login and when formatting the login error so no nil
dereference can occur during conn.Login or the error path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3f717e7f-d1d6-40ec-8c26-fbec69f16df0

📥 Commits

Reviewing files that changed from the base of the PR and between bb43881 and c1388a1.

📒 Files selected for processing (5)
  • internal/client/ftp/ftp.go
  • internal/client/sftp/auth.go
  • internal/client/sftp/config.go
  • internal/client/sftp/sftp.go
  • internal/client/sftp/sftp_test.go
💤 Files with no reviewable changes (1)
  • internal/client/sftp/sftp_test.go

Comment thread internal/client/sftp/sftp.go Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/client/ftp/ftp.go`:
- Around line 71-80: The code currently skips Login when u.User is nil which
allows init to succeed unauthenticated and fail later; change the logic in the
FTP initialization (the block referencing u.User, conn.Login and conn.Quit) to
fail fast: if u.User is nil either perform an explicit anonymous login via
conn.Login("anonymous","") or return a clear error immediately (e.g., "missing
FTP credentials"), and ensure you still call conn.Quit() on error and wrap the
login error (as with fmt.Errorf("can't login as %s: %w", ...)) for consistent
diagnostics.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 34107b97-ff55-4dce-8436-f765d5143714

📥 Commits

Reviewing files that changed from the base of the PR and between c1388a1 and 2a50167.

📒 Files selected for processing (3)
  • internal/client/ftp/ftp.go
  • internal/client/sftp/config.go
  • internal/client/sftp/sftp.go

Comment thread internal/client/ftp/ftp.go Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants