This article is focused on people who are interested in, first of all, automation of deployments, and secondly, for people who want to learn more about GitHub Actions. The article is intended to serve both, complete beginners who are venturing into their first foray into automated deployments, and the seasoned veterans of industry who know how to exit Vim and are curious about this (relatively) shiny, new deployment tool - GitHub Actions.
Virtually all of us are familiar with GitHub, the platform that provides storage for version-controlled software repositories. GitHub now also provides a compute service, called GitHub Actions, to perform operations such as packaging, deployment on GitHub itself instead of first fetching code into another tool/platform, and then working on it.
GitHub Actions consists of a YAML file that contains all the instructions that are to be executed on the repository along with some other meta-information like which operating system to run the steps on, which secrets to use, and so forth. GitHub Actions is really useful, not only because they allow you to write the required processing/packaging steps for the code right along with the code itself, but also because it is free! Well, somewhat. Most other cloud providers that give either finite amount of credits (ahem! GCP ahem!) or have a time limit associated with free-tier resources (not taking any names like AWS). GitHub Actions, on the other hand, has a free-tier with it’s quota refreshing every month. This is incredibly useful for someone, for example, that only wants to package their software and not rent a server to accomplish a fairly simple task.
Okay, enough talk, let’s start using GitHub Actions now! In the upcoming sections, we will deploy a simple web application to a server every time a new commit is made to the mas… Oops! I mean main branch!
Prerequisites
Before we begin, there are a few things that are required to be set up:
Let’s start setting up our repository both, locally and on GitHub.
Log into your GitHub Account by navigating to https://github.com/login (on a side note, enable 2-factor authentication for your account if you have not already!)
Click on the “New” button to create a new repository
Next, fill the details such as the repository name, description and it’s always a good idea to have a README.md for your repositories, and click on the “Create repository” button
On the repository page, click on the “Code” dropdown and copy the Git URL for the repo, HTTPS or SSH, whichever one works for you.
Now in a terminal window clone the repository locally by running the following command:
git clone
Now we can open the repository/folder with the code editor of our choice. I have used VSCode for this example.
Let’s add a single index.html file so we have something to serve as our web application.
<!DOCTYPE html>
<html>
<head>
<title>Kloudle Academy</title>
</head>
<body>
<p>Welcome to Kloudle Academy!</p>
</body>
</html>
This is how the files in the repository look now:
To be able to SSH into the server we want to deploy our web app to, we need an SSH key. Keep in mind, we also need to avoid committing the key to the repository as anyone with access to the repository will also have access to the key. A lot of meaningful workflows would need some kind of credentials to perform their actions - Pushing code to a server, fetching files from S3, uploading a scan report somewhere, etc. We can use GitHub secrets to add these secrets to our repository without having to commit them.
To add a secret to the repository, in our case the SSH Private key, perform the following steps:
Navigate to the repository’s settings page, click on the “Secrets” menu and then the “New repository secret” button.
Then give the secret a name (I prefer using all caps with underscores so it’s easy to identify secrets in the workflow), the secret value and click on the “Create secret” button.
Note: There are two kinds of secrets in GitHub - repository and organization. The difference between the two is that repository secrets are only available to the repository they are added for, while organization secrets are available to all repositories in the organization. Organization secrets are great to store credentials that are used by multiple repositories, it makes it much more convenient to rotate and revoke them if required. A quick factoid - if a secret is added with the same name to both, a repository and the organization, GitHub Actions will give precedence to the repository secrets and use it instead of the organization secret.
Before we can run our workflows on GitHub Actions, we need to enable our repositories for it. To enable Actions for the repository,
Navigate to the repository’s settings tab, select the “Action” menu item and ensure that the “Allow select actions” option is chosen along with only the “Allow actions created by GitHub” checkbox and click the “Save” button.
While any of the annotated options mentioned in the above screenshot would have worked, they have different levels of permissions on which sources in the Actions Marketplace we trust to run actions from:
Now that we have all permissions and secrets in place, let’s write the workflow file that would deploy our variant of the Kloudle Academy website.
Create the following directories inside the repository
cd /path/to/repo
mkdir -p .github/workflows
name: "Server Deployment"
on:
push:
branches: [main]
jobs:
deployment:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Say Hello!
run: echo "Hello there!"
A quick primer on the different sections present in the workflow:
git add .
git commit -m "Adding index.html and workflow file"
git push origin main
name: "Server Deployment"
on:
push:
branches: [main]
jobs:
deployment:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Say Hello!
run: echo "Hello there!"
- name: Deploy code to Server
env:
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
echo $SSH_KEY | base64 -d > ssh-key
chmod 400 ssh-key
ssh -i ssh-key -o StrictHostKeyChecking=no ubuntu@3.145.1.14 "cd /home/ubuntu/sample-app-deployment-with-github-actions && GIT_SSH_COMMAND='ssh -i /home/ubuntu/.ssh/ssh-key' git pull origin main"
8. Optionally, add a few changes to our _index.html _file so we can see our changes once deployed
We will repeat Step 3 to commit and push all updates to GitHub with the new commit message “Deploying changes!”
Repeating steps 4 and 5 for the latest build, shows us a successful deployment (ignore the build number in this image)
GitHub Actions is an amazing service that can be utilised to perform almost all kinds of operations on our code and repositories - packaging, deployment, etc. Although it does require buying a plan to unlock its full potential, the refreshing quota system present in the free-tier is a boon and is good for most individual projects. We took a look at an example where we deploy one static page to a server, but there could be other complex scenarios as well such as building a docker image and then deploying it to AWS’ Elastic Container Service, or GCP’s Cloud Run.
The idea of this blog is to provide building blocks with a brief introduction about GitHub Actions and workflows and enable the readers to start writing their own workflows. Some scenarios may require troubleshooting but once we get the hang of it, GitHub Actions becomes yet another tool in our DevOps tool belt.
This article is brought to you by Kloudle Academy, a free e-resource compilation, created and curated by Kloudle. Kloudle is a cloud security management platform that uses the power of automation and simplifies human requirements in cloud security. If you wish to give your feedback on this article, you can write to us here.