Skip to content

neziw/gradle-sftp-plugin

Repository files navigation

πŸš€ Gradle SFTP Plugin

License: MIT Gradle Java

Simple, lightweight, and modern Gradle plugin for uploading files via SFTP protocol


πŸ“‹ Table of Contents


✨ Features

  • πŸ” Secure File Transfer - Upload files securely using SFTP protocol
  • 🎯 Simple Configuration - Easy-to-use DSL for quick setup
  • πŸš€ Lightweight - Minimal dependencies, fast execution
  • πŸ”§ Gradle Integration - Seamlessly integrates with Gradle build lifecycle
  • πŸ“¦ Flexible - Support for custom ports, paths, and file locations
  • πŸ›‘οΈ Error Handling - Comprehensive error messages and exception handling
  • πŸ“ Logging - Built-in logging for upload status and debugging

πŸ“¦ Requirements

  • Gradle: 8.0 or higher
  • Java: 11 or higher
  • SFTP Server: Accessible SFTP server with valid credentials

πŸ”§ Installation

Using the Plugin DSL

Add the plugin to your build.gradle.kts:

plugins {
    id("ovh.neziw.sftp") version "1.0.0"
}

Using Legacy Plugin Application

If you're using the older plugin application method:

buildscript {
    repositories {
        maven {
            url = uri("https://plugins.gradle.org/m2/")
        }
    }
    dependencies {
        classpath("ovh.neziw.sftp:gradle-sftp-plugin:1.0.0")
    }
}

apply(plugin = "ovh.neziw.sftp")

πŸš€ Quick Start

Basic Example

plugins {
    id("ovh.neziw.sftp") version "1.0.0"
}

tasks.register<SftpTask>("upload") {
    host.set("sftp.example.com")
    port.set(22)
    username.set("myusername")
    password.set("mypassword")
    
    localFile.set(file("build/libs/my-app.jar"))
    remotePath.set("/home/user/applications/my-app.jar")
}

Run the task:

./gradlew upload

βš™οΈ Configuration

Task Registration

The plugin automatically registers a task named sftpUpload with default configuration. You can also create custom tasks:

tasks.register<SftpTask>("uploadToProduction") {
    // Configuration here
}

tasks.register<SftpTask>("uploadToStaging") {
    // Configuration here
}

πŸ“– Usage Examples

Example 1: Upload JAR Artifact

tasks.register<SftpTask>("uploadJar") {
    host.set("deploy.example.com")
    port.set(22)
    username.set("deployer")
    password.set(project.findProperty("sftp.password") as String? ?: "")
    
    val jarName = "my-application-${project.version}.jar"
    localFile.set(file("build/libs/${jarName}"))
    remotePath.set("/opt/applications/${jarName}")
}

Example 2: Upload with Dynamic Version

tasks.register<SftpTask>("uploadRelease") {
    host.set("releases.example.com")
    port.set(2222) // Custom port
    username.set("releaser")
    password.set(System.getenv("SFTP_PASSWORD") ?: "")
    
    val artifactName = "${project.name}-${project.version}.jar"
    localFile.set(file("build/libs/${artifactName}"))
    remotePath.set("/releases/${project.version}/${artifactName}")
    
    // Make upload depend on build
    dependsOn("build")
}

Example 3: Upload Multiple Files

tasks.register<SftpTask>("uploadDistributions") {
    host.set("dist.example.com")
    port.set(22)
    username.set("distuser")
    password.set(project.findProperty("sftp.password") as String? ?: "")
    
    // Upload main JAR
    localFile.set(file("build/libs/${project.name}-${project.version}.jar"))
    remotePath.set("/distributions/jar/${project.name}-${project.version}.jar")
}

tasks.register<SftpTask>("uploadSources") {
    host.set("dist.example.com")
    port.set(22)
    username.set("distuser")
    password.set(project.findProperty("sftp.password") as String? ?: "")
    
    // Upload sources JAR
    localFile.set(file("build/libs/${project.name}-${project.version}-sources.jar"))
    remotePath.set("/distributions/sources/${project.name}-${project.version}-sources.jar")
}

// Create a task that uploads both
tasks.register("uploadAll") {
    dependsOn("uploadDistributions", "uploadSources")
}

Example 4: Environment-Specific Configuration

val environment = project.findProperty("env") as String? ?: "development"

tasks.register<SftpTask>("uploadToEnvironment") {
    when (environment) {
        "production" -> {
            host.set("prod-sftp.example.com")
            username.set("prod-user")
            remotePath.set("/prod/applications/")
        }
        "staging" -> {
            host.set("staging-sftp.example.com")
            username.set("staging-user")
            remotePath.set("/staging/applications/")
        }
        else -> {
            host.set("dev-sftp.example.com")
            username.set("dev-user")
            remotePath.set("/dev/applications/")
        }
    }
    
    port.set(22)
    password.set(project.findProperty("sftp.password") as String? ?: "")
    localFile.set(file("build/libs/${project.name}-${project.version}.jar"))
}

Example 5: Integration with Build Lifecycle

tasks.register<SftpTask>("deploy") {
    host.set("deploy.example.com")
    port.set(22)
    username.set("deployer")
    password.set(System.getenv("DEPLOY_PASSWORD") ?: "")
    
    val artifactName = "${project.name}-${project.version}.jar"
    localFile.set(file("build/libs/${artifactName}"))
    remotePath.set("/var/applications/${artifactName}")
    
    // Ensure build completes before deployment
    dependsOn("build")
    
    // Only run if build was successful
    mustRunAfter("build")
}

πŸ” Task Properties

Property Type Required Description Default
host String βœ… Yes SFTP server hostname or IP address "your-host.com"
port Integer βœ… Yes SFTP server port number 22
username String βœ… Yes SFTP server username "your-username"
password String βœ… Yes SFTP server password "your-password"
localFile File βœ… Yes Local file to upload file("build/libs/your-library.jar")
remotePath String βœ… Yes Remote path where file will be uploaded "/path/to/remote/your-library.jar"

πŸ’‘ Best Practices

1. Secure Credential Management

Never hardcode passwords in your build files. Use Gradle properties or environment variables:

// In gradle.properties (not committed to VCS)
// sftp.password=your-secure-password

// In build.gradle.kts
password.set(project.findProperty("sftp.password") as String? ?: "")

Or use environment variables:

password.set(System.getenv("SFTP_PASSWORD") ?: "")

2. Use Gradle Properties File

Create a gradle.properties file (and add it to .gitignore):

sftp.host=your-sftp-server.com
sftp.port=22
sftp.username=your-username
sftp.password=your-password

Then reference it in your build:

tasks.register<SftpTask>("upload") {
    host.set(project.findProperty("sftp.host") as String? ?: "")
    port.set((project.findProperty("sftp.port") as String?)?.toInt() ?: 22)
    username.set(project.findProperty("sftp.username") as String? ?: "")
    password.set(project.findProperty("sftp.password") as String? ?: "")
    // ...
}

3. Task Dependencies

Always ensure required tasks complete before upload:

tasks.register<SftpTask>("upload") {
    dependsOn("build")
    // ...
}

4. Error Handling

The plugin includes built-in error handling, but you can add custom error handling:

tasks.register<SftpTask>("upload") {
    // ... configuration ...
    
    doLast {
        if (!localFile.get().exists()) {
            throw GradleException("Local file does not exist: ${localFile.get().absolutePath}")
        }
    }
}

πŸ› Troubleshooting

1. Connection Issues

Problem: Cannot connect to SFTP server

Solutions:

  • Verify host and port are correct
  • Check network connectivity: telnet <host> <port>
  • Ensure firewall allows SFTP connections
  • Verify credentials are correct

2. Authentication Failures

Problem: Authentication failed

Solutions:

  • Double-check username and password
  • Ensure the user has write permissions on the remote path
  • Verify the user account is active

3. File Not Found

Problem: Local file does not exist

Solutions:

  • Verify the file path is correct
  • Ensure the build task has completed successfully
  • Check file permissions

4. Permission Denied

Problem: Permission denied on remote path

Solutions:

  • Verify the user has write permissions
  • Check if the remote directory exists
  • Ensure the remote path is accessible

πŸ”§ Advanced Configuration

Custom Task Names

tasks.register<SftpTask>("customUploadTask") {
    // Your configuration
}

Conditional Uploads

tasks.register<SftpTask>("conditionalUpload") {
    onlyIf {
        project.hasProperty("upload.enabled") && 
        project.property("upload.enabled") == "true"
    }
    // Configuration
}

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


πŸ™ Acknowledgments

  • Built with JSch for SFTP functionality
  • Inspired by the need for simple SFTP uploads in Gradle builds

πŸ“ž Support

If you encounter any issues or have questions, please open an issue on the GitHub repository.


Made with ❀️ by neziw

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages