Using FTP in GitHub Actions

December 2nd 2022 GitHub

FTP is still one of the most common methods to upload files to your web server. So it's not surprising that there are (too) many GitHub actions for it. However, if you want to download some files (e.g. to backup/commit content that was edited online), you are mostly out of luck.

Even actions that use LFTP under the hood limit the supported operations and make it (almost) impossible to use them to download files from the server. Fortunately, you can use LFTP directly without creating a custom action. The program is not installed by default in runners, but nothing prevents you from installing it as part of your workflow:

- name: Install lftp
  run: sudo apt install lftp

After that, you can use LFTP however you like. For example, the following command lets you download all files from the userfiles folder that are newer than those in the Git repository (the first path is the server path, the second path is the local path):

- name: download userfiles
  run: lftp -c "set ssl:verify-certificate false; open -u ${{ secrets.FTP_USERNAME }},${{ secrets.FTP_PASSWORD }} ${{ secrets.FTP_HOST }}; mirror -n -v www/userfiles userfiles"

If you want to test your workflow locally before publishing them to GitHub, the operation will fail with one of the following errors, depending on which runner you chose:

E: Unable to locate package lftp

sudo: command not found

This does not mean that it will also fail when run in GitHub Actions, since the local runner is not exactly the same as the one in GitHub Actions. However, you can try using a different Docker image for your local runner before abandoning local testing.

catthehacker/ubuntu:full-20.04 was a good alternative for the ubuntu-20.04 runner I used. To use it, you can either change the default image in the ~/.actrc file or specify it with the -P option, as seen in the following command I used to test my workflow:

act workflow_dispatch -P ubuntu-20.04=catthehacker/ubuntu:full-20.04 -s FTP_HOST=ftp.my-host.com -s FTP_USERNAME=myUsername -s FTP_PASSWORD=myPwd

The above command also specifies workflow_dispatch as the event that triggers the workflow, as well as any secrets required for the workflow (with the -s option).

Even if your workflow succeeds locally, it's possible that it will fail in GitHub Actions for some reason. For example, when I tried to use this workflow, the LFTP command just waited without doing anything until it finally timed out (or I cancelled it). It took me a while to figure it out, but it turned out that it was not a problem with GitHub Actions. It was the hosting provider's fault for blocking FTP access for IPs from other countries. I confirmed this theory by trying to run the workflow locally while connected to US VPN. The symptoms are identical. To work around this problem, you need to unblock the IPs or use a self-hosted runner that is in the correct country.

When creating workflows for GitHub Actions, remember that you can already accomplish a lot with shell commands and do not always have to find an action in the marketplace to accomplish your goal. You may even have more control with this than with an action. In this post, I used this approach to download some files from a web server via FTP.

If you're looking for online one-on-one mentorship on a related topic, you can find me on Codementor.
If you need a team of experienced software engineers to help you with a project, contact us at Razum.
Copyright
Creative Commons License