Skip to content

[sftp] add support#8

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

[sftp] add support#8
capcom6 wants to merge 2 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 (SSH File Transfer Protocol) support alongside existing FTP capabilities for remote file synchronization.
  • Documentation

    • Updated README with SFTP usage examples and configuration details.
    • Updated CLI help text to reflect FTP and SFTP server options.

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

Warning

Rate limit exceeded

@capcom6 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 32 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1e18b98d-eaeb-4501-93d1-b37427b550a3

📥 Commits

Reviewing files that changed from the base of the PR and between 39cc868 and 43e2de0.

📒 Files selected for processing (3)
  • README.md
  • internal/client/sftp/sftp.go
  • internal/client/types/errors.go

Walkthrough

This PR implements SFTP protocol support alongside the existing FTP functionality. The changes include refactoring the FTP client to use a shared package structure, adding a complete new SFTP client implementation with SSH connection management and remote filesystem operations, routing FTP/SFTP schemes through a factory, and updating documentation and CLI help to reflect both protocols. Dependencies are bumped to support SSH/SFTP connectivity.

Changes

SFTP protocol support

Layer / File(s) Summary
Shared error types foundation
internal/client/types/errors.go
Error definitions moved from internal/client to internal/client/types package so FTP and SFTP implementations share error values.
FTP client refactoring for shared package structure
internal/client/ftp/ftp.go
FTP client type renamed from FtpClient to Client within the ftp package; imports updated to use shared types errors; all method receivers and error references updated accordingly.
SFTP client implementation
internal/client/sftp/sftp.go
New SFTP client with SSH connection initialization, connectivity ping, nested directory creation, recursive directory removal, file upload with parent directory creation, file removal, and intelligent removal dispatch; includes error classification and path traversal helpers.
Client factory scheme routing
internal/client/client.go
Constructor imports both ftp and sftp packages and routes URL schemes to ftp.NewFtpClient or sftp.NewSftpClient; unsupported schemes return error wrapping shared types.ErrUnsupportedScheme with supported scheme names.
Documentation and CLI help updates
README.md, main.go, internal/cli/commands/sync/sync.go
README, main.go, and sync.go help texts updated to advertise FTP or SFTP support; SFTP port examples and URL format descriptions added; Roadmap marks SFTP support completed.
Dependency and tooling updates
go.mod, .golangci.yml
Go toolchain bumped to 1.25.0; SSH/SFTP dependencies added (golang.org/x/crypto, github.com/kr/fs); golangci.yml excludes SSH config types from exhaustiveness checks.

Sequence Diagram

sequenceDiagram
  participant Caller
  participant ClientFactory as client.New()
  participant FtpClient as ftp.NewFtpClient
  participant SftpClient as sftp.NewSftpClient
  
  Caller->>ClientFactory: New(address, logger)
  alt URL scheme is "ftp"
    ClientFactory->>FtpClient: NewFtpClient(url, logger)
    FtpClient-->>ClientFactory: *ftp.Client
  else URL scheme is "sftp"
    ClientFactory->>SftpClient: NewSftpClient(url, logger)
    SftpClient-->>ClientFactory: *sftp.Client
  else unsupported scheme
    ClientFactory-->>Caller: error(ErrUnsupportedScheme with "ftp, sftp")
  end
  ClientFactory-->>Caller: Client interface, error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

The PR introduces a substantial new SFTP client implementation (312 lines) alongside refactored FTP logic and factory routing, requiring careful review of connection initialization, mutex-protected state, error handling strategies, and filesystem operation semantics across both protocols. The changes are moderately heterogeneous (new implementation, refactoring, documentation, configuration) but follow a clear pattern; most complexity is localized to the SFTP client's initialization and recursive operations.

Possibly related PRs

  • capcom6/sftp-sync#5: Prior PR added the logger parameter to the client.New factory; this PR extends that same factory with FTP/SFTP scheme routing and shared error handling.

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 convey meaningful information about what SFTP support entails or how it integrates. Use a more specific title like 'Add SFTP client implementation and protocol support' to clearly describe the main 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 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
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