Deploying from git via ftp

Lets take advantage of GitLab’s Continuous Integration support, known as gitlab-ci. The project in question will have to be hosted on, unless you have your own (perhaps Dockerized) GitLab and want to implement your own runners.

I use this for websites – deploying straight from git to a staging site – but it’s designed to build and test your code for other projects, too.

GitLab hosts a quick-start guide here – the short version is that we’ll be including a gitlab-ci.yml file at the root of our git project. You can also find a gitlab-ci.yml reference here.

Our very basic continuous deployment consists only of our nominated ftp tool – lftp in our case – and the command to mirror the file structure to the ftp server, excluding the .git/ folder and the .gitlab-ci.yml file itself. Here’s what it looks like:

LFTP is a pretty nifty piece of software that lets us perform our upload in one line. First it disallows SSL; without it, you won’t be able to connect to a shared website hosting service. Next it opens a connection to our ftp host, then it mirrors the git repository directly to the root of the ftp server (so make sure your ftp login corresponds to the correct folder).

A quick look at the switches:
-R: reverses the mirror – uploading to the remote rather than downloading from it.
-n: only newer files. This avoids uploading identical files for no reason.
-e: deletes any files on the remote that aren’t present in the git repository. Cleans up removed files.
-v: verbose – so our GitLab-CI build log shows which files get transferred.
–ignore-time: Forces our only-newer switch to work off file size rather than times which will likely be incorrect.
–parallel=10: Upload 10 files at a time. GitLab’s server and the remote host can both handle this just fine.
–exclude-glob .git*: Ignores .gitlab-ci.yml, .gitignore, etc.
–exclude .git/: Self explanatory.

You can find a more in-depth explanation here at the lftp man page.

You’ll notice the shell variables USERNAME, PASSWORD, and HOST. Primarily this is to keep credentials out of committed files, but has the added benefit of our gitlab-ci.yml file being universal. You can add these variables in via your Project Settings > Variables on GitLab and they’ll be included in the runner that deploys your files.