Automating GitHub workflow
GithubActions is CI/CD platform that allows automating processes going on in our repositories. What can be automated? Anything that we would require us logging to a server and running bunch of commands in ssh terminal. From pulling new code, building the app, running tests to restarting app on server.
My blog is hosted on MIKR.US, an amazing and really cheap VPS platform great for side projects. Everytime I push new code to repo I need to connect to my server via SSH, navigate to app directory and run several commands. In this post I will show you how to automate these steps.
To start we need to create a directory in the root of our project.
.github/workflows
We then will create a yaml file named after workflow we are developing, since I want to automate deployment it will be:
.github/workflows/staging-deploy.yaml
There are 2 keywords that require explanation here 💡
- workflow is this configurable automated process that can run one or more jobs when triggered. It's customised in the yaml file. One repository can have multiple workflows with different tasks triggered on different events each. You can have one workflow run build and tests when PR is created, another one can deploy app when release is created, and another workflow can be adding labels to issues when new ones are opened.
- triggers cause workflows to run. Workflows can be triggered manually from github platform, on schedule, or by events in repository (for example creating a PR) or outside of GitHub
This is my workflow code:
On key defines which action casuses workflow to run. Event triggering my workflow is workflow_dispatch which means manual running the workflow from repos github page. Which still is a huge time saver. It will allow me to go to my repo, click Actions tab and just run it.
Each workflow is made up of one or more jobs. Each of them runs in a runner environment that is specified in runs-on key. Job contains a sequence of tasks called steps.
Reusable actions ♻️
Sometimes we might want to use a ready made action, reusable unit of code in our workflow. For that we have keyword uses that points to action defined in same repository, in public repository or in a published Docker container image. We are using a public action for connecting to server with ssh:
#{owner}/{repo}@{ref}
appleboy/ssh-action@master
Public actions will have documentation on how to incorporate them into you workflow. Here we are using with keyword to create a set of environment variables required for action. We wil need to then provide them in our repo settings like this:
⚠️ When you start a repo you will not see any secrets. You need to create them! Make sure that all the secrets you created are named exactly the same ⚠️
After setting environment variables we need to add a list of commands that we would otherwise type in manually on the server. What are they?
- Navigate to blog frontend directory
- Pull code from repository
- Build Next app
- Restart running pm2* process
If you have successfully added your secrets you should be able to run your action from github.
Setting up multiple repos on server 🚥
However I had one problem I could not figure out until I got to this section of github keyd managing docs.
When workflow got to the step where I needed to pull code from repo I got permission denied error. What I needed to do is set separate keys for my repos (I have more than one repo on my VPS).
🔑 First generate new keys in your .ssh folder on your server for each of your git repos. I left passphrase empty, otherwise the script would not complete git pull. Read about key generation procedures here In short use this command from github docs:
### remember to use your own email
$ ssh-keygen -t ed25519 -C "[email protected]"
For that you need to create an ~/.ssh/config file and create aliases for your repos like this:
### this files resides here ~/.ssh/config
Host github.com-go-jo-waystar
Hostname github.com
IdentityFile=/home/user/.ssh/repo-0_deploy_key
Host github.com-repo-1
Hostname github.com
IdentityFile=/home/user/.ssh/repo-1_deploy_key
Then in each of the repos you added your ssh alias to you will need to change this in remote "origin" url section of your repos .git/config. So on your server in app folder run:
nano .git/config
and then just substitute your url with your repo alias like this
[remote "origin"]
## url = git@{SSH_ALIAS}:{OWNER}/{GITHUB_REPO_NAME}
url = [email protected]:kendallroy/go-jo-roy.git
I found this discussion on stackoverflow helpful in solving this problem.
Now every time I push to my repo I can run GitHub action without logging to my server and doing all the steps manually. Later on I might want to trigger this workflow on a different event.