Skip to content

matteolutz/ftp-deploy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ftp-deploy

A small, fast CLI tool to deploy a directory to an FTP server by tracking file hashes and uploading only changed files.

  • Uses a local tracking store (.ftp/files.json) that stores SHA-256 hashes of files.
  • Scans the project tree in parallel, computes hashes, and uploads only changed (or forced) files.
  • Creates missing directories on the remote FTP server as needed.
  • Supports pre-deploy hooks and a simple JSON-based config/credentials format.

License

Table of contents

Features

  • Fast file collection with parallel directory walk (num_cpus for worker count)
  • SHA-256 based change detection to only upload modified/new files
  • Progress bar for uploads
  • Automatic creation of remote directories (walks path components and mkdir/cwd)
  • .ftpignore support (default file created with .ftp/)
  • Pre-deploy hook execution (shell on Unix, cmd on Windows)
  • Simple JSON configuration and credentials stored in the project directory

Quick start

Prerequisites

  • Rust toolchain (cargo + rustc)
  • An FTP server and account

Build and run locally

# clone
git clone https://github.com/yourname/ftp-deploy.git
cd ftp-deploy

# build
cargo build --release

# run
./target/release/ftp-deploy --help

(Optional) Install to your cargo bin

cargo install --path .

Commands

1) init

Initializes the current directory (or given path) with default configuration, credentials and tracking files.

Usage:

ftp-deploy init
# or initialize a specific path
ftp-deploy init --path /path/to/project

What it creates:

  • ftp-deploy.json — project config (hooks)
  • ftp-deploy-creds.json — credentials and remote base path
  • .ftp/. (tracking directory)
  • .ftp/files.json — generated by the first run to track file hashes
  • .ftpignore — default contains ".ftp/"

2) deploy

Compute file hashes, compare with tracked hashes and upload updated files.

Usage:

ftp-deploy deploy
# options:
# --path, -p      Directory to operate on (defaults to .)
# --jobs, -j      Number of threads for file walk (defaults to number of CPUs)
# --force, -f     Force upload of all files even if hashes match
ftp-deploy deploy --path /path/to/project --jobs 8

3) files

List all files considered/tracked by the collector (honors .ftpignore).

Usage:

ftp-deploy files
# list files under a different path:
ftp-deploy files --path /path/to/project

Configuration files

  • ftp-deploy.json (FtpConfig)

    • Fields:
      • hooks: array of shell commands to run prior to deployment
    • Example:
      {
        "hooks": ["npm run build", "cargo build --release"]
      }

    Hooks are run via:

    • sh -c "<hook>" on Unix
    • cmd /C "<hook>" on Windows
  • ftp-deploy-creds.json (FtpCreds)

    • Fields:
      • server: FTP server address (host:port)
      • base_path: remote base directory (uploaded files are joined on this path)
      • username
      • password
    • Example:
      {
        "server": "ftp.example.com:21",
        "base_path": "/www/my-site",
        "username": "deploy",
        "password": "hunter2"
      }
  • .ftpignore

    • Default created with a single entry: ".ftp/"
    • Acts like .gitignore for the collector (the project uses ignore::WalkBuilder)
  • .ftp/files.json (FilesTracking)

    • Stores a JSON map of local Path -> SHA-256 hex digest for previously-deployed files.
    • Created/updated automatically by the tool.

How it works (internals)

File collection:

  • Walks the filesystem using ignore::WalkBuilder and respects custom ignore file (.ftpignore).
  • Uses SHA-256 (sha2 crate) to compute file hashes.
  • Scans in parallel with configurable number of threads (num_cpus default).
  • Builds a list of changed/added files compared to .ftp/files.json, unless --force is used.

Upload:

  • Connects using the ftp crate and logs in with credentials from ftp-deploy-creds.json.
  • For each file to upload:
    • Ensures remote directory exists by walking path components and calling mkdir/cwd (cwd_or_create_recursive).
    • Calls ftp.put(file_name, reader) to upload the file.
  • Shows an indicatif progress bar during upload.

Notes & current limitations / TODOs

  • File path handling: The current implementation uploads files to creds.base_path joined with the local file path. Be mindful of how local paths map to remote directories.
  • The upload loop currently always attempts mkdir/cwd for each file; an optimization could be to sort files and reduce redundant mkdir/cwd operations (commented TODO in code).
  • Credentials are stored in plaintext JSON inside the project directory. Make sure file permissions are appropriate for your security needs.

Examples

Initialize a project and deploy:

# initialize current directory with default files
ftp-deploy init

# edit ftp-deploy-creds.json to add your server/username/password/base_path
# optionally edit ftp-deploy.json hooks

# perform a deploy
ftp-deploy deploy

Force upload every file (ignore tracking):

ftp-deploy deploy --force

Specify a custom jobs count for hashing pass:

ftp-deploy deploy --jobs 12

License

This repository is provided under the MIT License by default. Change as necessary for your project. See LICENSE file.


NOTE: This README file was generated using generative AI.

About

ftp-deploy - a small, fast CLI tool to deploy a project to an FTP server.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages