Make Deployment Easy with Continuous Delivery and GitHub Actions
By: Pablo T. Campos
Tags: Github Actions, Programming, Continuous Delivery, Deployment, Continuous Integration

Learn how CD can save you hundreds of hours

Photo by jesse ramirez on Unsplash

Deployment is always a complicated and tedious task. As your applications grow, you will probably need to ship to production many times a week, and doing so rapidly is usually crucial. Luckily for you, thanks to Continuous Delivery and GitHub Actions, deploying to production becomes a trivial task!

What is CD?

Continuous Delivery or CD is the agile practice of continuously deploying to production bit size pieces of code, instead of in big chunks. This way, not only your application can grow more steadily, but it also becomes way easier to identify bugs in small commits than in massive pieces of code. CD is at its best when combined with Continuous Integration or CI.

CI parts from the same principle of managing your application changes in small, more manageable parts, but contrary to CD, CI is responsible for verifying that new changes to the code base work as intended. This way, CD will only step in to deploy new changes if they work as intended!

The beauty of CI and CD is that they can be fully automatized thanks to GitHub Actions! Every time a commit is made to the main branch, we can trigger a workflow that runs tests on our code and if they pass, our code gets deployed to production. All you will have to worry about is pushing your code to your repository and fixing any bugs that may occur.

To learn more about GitHub Actions and how to create workflows, check out my previous article on CI.

In this article, I will be mainly focused on the contents of a proper CD workflow.

Enabling CD

At the end of the day, deployment consists of logging into a server and running certain commands.

Generating SSH keys

For logging into our production servers we are going to need a pair of ssh keys: a secret key or SK and a public one or PK. To generate them, run on your local computer

$ ssh-keygen -m PEM -t rsa -b 4096

Generating public/private rsa key pair.

Enter file in which to save the key (/home/paburo/.ssh/id_rsa): name

where name stands for the name of the key pair. For the purpose of the tutorial let's set name to cd. When the command has finished, we should now have two new files on the ~/.ssh directory.

$ ls ~/.ssh

cd cd.pub

We now need to copy the contents of our secret key and save it on GitHub as a repository secret.

$ cat ~/.ssh/cd

-----BEGIN RSA PRIVATE KEY-----

MIIJJwIBAAKCAgEAlmBMQtfsLjOADd3mAuq5qqifiynSJzGN3dy3qJed8MCDZv7S

[...]

ty9wnmRiqhzl2wzuA7TVyq6X40IOOdPp910CFQrRMPaJPV1/y2KjMwMLF0/cdVNG

RHhuExEbTzMa+zYjDtt0nBERRiR0tiy/3fBfFOylWtyzkH4Hvz9gBYGOwQ==

-----END RSA PRIVATE KEY-----

Head over to your GitHub repository, click on Settings > Secrets > New repository secret and create a GitHub secret with the contents of your private key under the name of CD_SK.

Once you have saved the secret, it is good practice to delete your private key from your computer, but be careful as you will not be able to see your key from the GitHub secret.

$ rm ~/.ssh/cd

Now we need to add the contens of the public key, cd.pub to our server authorized_keys file. First, let’s grab the contents of the public key

$ cat ~/.ssh/cd.pub

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCWYExC1+wuM4AN3eYC6rmqqJ+LKdInMY3d3Leol53wwINm/tK1uHRKU9UilpYIvadV9UxSyIDueHgpcME6Yqjjt9KxFIxSGtrvN6RWxLGGjl0HMYoe5bETwOyrF7MT69whe9AFOlX2WYzqXbbeqaHlvoFYp/M5woFQQo2LTZ/OUHpUT/4ODsmlNgSNA0L70GRonEXj8QRwWyhEMSWk/h5S6iCfQg2TGLW+c6F6lj0+izo6DahdKPiW6j4IsSvV52gyXdfX28Mo3XeEeIXaNXSW5VANSKbJ5aZ4pfgnmfTDmPI9p73SeTsCzisAxTpVZN0OilL+I/MvVkAKtCQLdzQANVM6gFolz8xjfjTGtu1xFLo/V1dlGe+IvkSvVJIeecrMtPudmOTR1lre/JcDGb3ntbFjQuNfDaqc6jEgsFDmub+J7rvORzJumfLl+1fe4BdMA4Rl7oLPHb1I9pFhO3vYuAd+2+FpXOygIC+pDlznjpTwfdXoJkm9M4Q5SzoCmgfkkbKaLhmRhyP7QuEv6FALfIF98FIvLiRcMpjK6+SHiq684dxce8yMbKdmdfRuwR+7t9/K5OLF3KB67uZQGaRZYZsCxMsk76Z7joANCm+5YoPEyxck8CQ1ArYC+TlHfZU9O1uKvjlqdiffbJbcVSDAy24OiXkvpNWzV+bFX15ULw== paburo@paburo-ThinkPad-XXXX

and now ssh into your server, which can be done with

$ ssh user@ip

where user is your user at your server, ip . From your server, open the authorized_keys file with a text editor of your liking and paste the contents of your public key at the bottom.

$ nano ~/.ssh/authorized_keys

CD Workflow

Now that we have generated and configure our SSH key pair for accessing our server, it is time to create a workflow that will log into the server and run commands for us.

Lets break this workflow down. This workflow can be triggered manually or every time a push or pull request is made to the master branch. Once it has been triggered it will carry out the CD job .This job will use a marketplace action made by appleboy to ssh into our server. It takes four arguments: host , the domain or ip of your server; username , the username of your server; key , the secret key we previously created; port , which for SSH connections defaults to 22 and script , which are the commands that we wish to run on our server once the workflow logs in via SSH.

The script argument may vary wildly depending on your application. In this example, you can see how I chose to deploy a Django App: I cd into the project directory, pull from the git repository, install all the requirements and restart the service in charge of my App.

Final Thoughts

And that is it! Now you can relax and breath out as your deployment process is carried out automatically every time you push your code to your repository! Continuous Delivery is a great tool on its own, but be sure to use it together Continuous Integration to unlock its full potential.

As always, feel free to contact me if you need to. All the code found in this tutorial is freely available on GitHub.

Happy Continous Deployment!

Thank you