/swift

Publish Deployment with Rsync

John Sundell's Swift-based static site generator "Publish" comes with a single built-in deployment method: Git. If this is how you publish (e.g., to GitHub Pages), all you need to do to update your site, is run "publish deploy". Nice and dandy, right?

If you depend on another, more custom deployment method, perhaps something like rsync, you're on your own. Luckily, the Publish framework gives you an integration point, so you can make your custom deployment method fit in just like the built-in Git method.

Rsync'ing a directory

If you're not so familiar with the rsync command, I'll save you some sleuthing. This is the basic structure, if all you need is a recursive sync to an SSH location. The backslashes spread the command across multiple lines but have no further effect:

rsync \
-a \
-e "ssh -p 21098 -i ~/.ssh/jarroo-hosting" \
Output/ j######p@1##.###.###.##0:swiftlabs.jarroo.com

A line by line breakdown:

  • rsync
  • -a: recursively traverse, and maintain all attributes
  • -e "ssh (..)": overrides some of the defaults of the underlying SSH connection
    • -p 21098: set the SSH port to 21098
    • -i ~/.ssh/jarroo-hosting: select a specific identity file, in this case the "jarroo-hosting" public/private key pair on my system
    • Output/ j######p@1##.###.###.##0:swiftlabs.jarroo.com: Output/ stands for the source directory, and the second part describes the target location, according to the following structure: <username>@<host>:<directory>

Implementation

The built-in Git deployment method is implemented as a static factory method, so let's do the same.

try JarroolabsSwift().publish(
    withTheme: .jarrooTheme,
    deployedUsing: .rsync(), // <-- 
    plugins: [.splash(withClassPrefix: "")]
)

extension DeploymentMethod {
    static func rsync() -> DeploymentMethod {
        DeploymentMethod(name: "Rsync") { context in
            let folder = try context.createDeploymentFolder(withPrefix: "Rsync", configure: { _ in })
            do {
                try shellOut(
                    to: """
                    rsync \
                    -a \
                    -e "ssh -p 21098 -i ~/.ssh/jarroo-hosting" \
                    \(folder.path) j#####p@1##.###.###.##0:swiftlabs.jarroo.com
                    """,
                    at: "~/"
                )
            } catch let error as ShellOutError {
                throw PublishingError(infoMessage: error.message)
            } catch {
                throw error
            }
        }
    }
}

Some clarifications:

  • let folder = try context.createDeploymentFolder(...) gives you a handle to the temporary directory Publish uses, which contains your deployment
  • try shellOut(...) allows you to execute a shell command. This is where you'll paste your rsync command. folder.path will point to your deployment directory.

That's all, really. You should now be able to run publish deploy from the Terminal ✨.

Tagged with: