Parallel incremental FTP deploy in CI pipeline
Tags: tutorial, devops, docker, php
Published: 2020-11-18 13:01:48

Automatization of deployment is must-have nowadays. There are several tools that can upload files to FTP. But none of them can upload only changes and do it in parallel. I combined two tools to achieve this, with examples for Gitlab.

> 🇨🇿 V češtině si lze článek přečíst na [kutac.cz](https://www.kutac.cz/pocitace-a-internety/paralelni-inkrementalni-ftp-deploy-v-ci-pipeline)

**TL;DR** Everything described in the article is in the [public repository](https://gitlab.com/pavel.kutac/docker-ftp-deployer) with ready-to-go [Docker image](https://gitlab.com/pavel.kutac/docker-ftp-deployer/container_registry) and examples for the Gitlab CI pipeline.

---

# FTP Deployment + LFTP = Parallel incremental upload

Earlier I have forked and modified [FTP Deployment](https://github.com/arxeiss/ftp-deployment) tool. Which can compute hashes of all files, compares it with `.htdeployment` file saved on the server, and creates/uploads/deletes only changed files. However, it cannot work in parallel.

But there is another great and popular tool called [LFTP](http://lftp.yar.ru/) which can do parallel operations. It also supports `mirror` command, but that cannot be used in many cases. More about that below.

In [my project](https://gitlab.com/pavel.kutac/docker-ftp-deployer), I used the modified fork of FTP Deployment to track changes and prepare lists of directories and files to upload or delete. The second step consists of Bash scripts consuming lists and executing LFTP commands.

> ℹ️ Thanks to the combination of both tools my deploy pipeline works much faster. With many changed files in the vendor folder, I can see time decreasing from 30 minutes to 5 minutes.

See the [README](https://gitlab.com/pavel.kutac/docker-ftp-deployer/-/blob/master/README.md) and [example files](https://gitlab.com/pavel.kutac/docker-ftp-deployer/-/tree/master/example) to see detailed explanation and ready-to-go config files. And also prepared [Docker image](https://gitlab.com/pavel.kutac/docker-ftp-deployer/container_registry) which is based on the newest PHP and contains a modified version of FTP Deployment, LFTP, and utilities to replace environment variables and a few more.


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/l7dgd0cpr0himbg65jb6.png)

## Why `lftp mirror` cannot be always used?

The `mirror` command of LFTP can synchronize 2 folders, so someone could say that FTP Deployment is superfluous. And in some cases, it could really be true. However, LFTP checks only filesize and file's modification time. If there is a difference between a local file and a file on FTP, the file is synced. But this has many flaws:

1. Some FTP servers ignore modification time sent with file and just set current time. Due to this behavior, the file should be synced always.
1. If some files are created in the pipeline, their modification time can be different between runs. So they could be always considered as changed. For example vendor folder.
1. Both issues above can be solved with `--ignore-time` flag. Then the only filesize is checked when files are compared. But if only 1 character is changed in the file, the file will not be synced, which is not sufficient for production use.

---

Let me know what do you think about my solution!