Automating your routine with Github Actions
Everyone sometimes gets obsessed with automation, trying to make a magic button "Create app" that does all the job for you. In this article, I'll try to get a little closer to that dream with Github Actions.
We'll set up the next simple workflow:
- With the push to a specific branch, git actions will be triggered
- Run tests and make sure they all pass
- Build project
- Send build files to the server with ssh authentication
I assume, you have a project stored on github and server with ssh authentication.
Prerequirements
Before we dive deep into coding, we need to set up some secrets. In this case, we need to have only private ssh key, so we can access our server from Github Actions. To not keep it hardcoded, we'll store it inside our repository secrets. Copy your private ssh key, associated with your server, and place it in project's secrets like follows:
Next thing we need to create a .github/workflows folderr structure in the root directory of the project. Then, we need to create our first workflow file demo.yml
.
Your project structure might look like this
Filling our workflow file
Let's fill our demo.yml file with next content:
name: GitHub Actions Demo
on:
push:
branches:
- master
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run test
build:
needs: [test]
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- run: set -eu
- run: mkdir "$HOME/.ssh"
- run: echo "${{ secrets.SSHKEY }}" > "$HOME/.ssh/id_rsa"
- run: chmod 600 "$HOME/.ssh/id_rsa"
# Build
- run: npm ci
- run: npm run build
# Deploy
- run: cd dist && rsync -e "ssh -i $HOME/.ssh/id_rsa -o StrictHostKeyChecking=no" --archive --compress --delete . username@ip:/path/to/place/build
Let's go line by line and see what's this all about!
Here we specify the name of our workflow:
name: GitHub Actions Demo
This limits our workflow to run only when we push to the master branch:
on:
push:
branches:
- master
There are a lot of different options here, like a limit to work with pull requests, tag creation, etc. You can read a list of available actions here.
We have just 2 jobs: test and build.
"test" job
strategy.matrix
allows us to define special variables for our jobs. In our case, we need to run "test" job using latest 12 version of node:
strategy:
matrix:
node-version: [12.x]
What's so special about matrix variables? They allow to run multiple jobs for each value in the list. If you wish to run your tests on several node versions, you can do it like this: node-version: [10.x, 12.x]
. And 2 jobs will run for each version.
In steps
section we define our steps for the job to execute.
uses
keyword says, that we're about to use some external workflows to do some stuff. In our case, there are 2 workflows: to checkout our project, so Github Actions can have access to it, and to set up node.
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
You can check out all of the official actions, or you can even create your own snippet and place it on github, so everyone can use it. Let's go, opensource!
Then we need to install our dependencies and finally, run our tests from the test
script in package.json
. run
keyword allows to use commands you want to execute.
- run: npm ci
- run: npm run test
npm ci
is similar to npm install, except it's meant to be used in automated environments such as test platforms, continuous integration, and deployment -- or any situation where you want to make sure you're doing a clean install of your dependencies.
"build" job
First steps are almost the same, except the needs: [test]
part. This line tells, that we need to wait for job "test" to pass and only after that run "build" job. If tests fail, the build won't run. Great, that's exactly what we want!
Next, we need to set our ssh key under the .ssh folder. We take this key from secrets
variable, which contains all our secrets that we set a couple of steps earlier.
- run: set -eu
- run: mkdir "$HOME/.ssh"
- run: echo "${{ secrets.SSHKEY }}" > "$HOME/.ssh/id_rsa"
- run: chmod 600 "$HOME/.ssh/id_rsa"
The very last step is to build our project and, using rcync command, transfer our dist folder to the server. Also, we need to pass our ssh key for successful authentication.
Don't forget to change username@ip:/path/to/place/build to actual values
Important note: This approach might not work if you have a passphrase wall on your server
# Build
- run: npm ci
- run: npm run build
# Deploy
- run: cd dist && rsync -e "ssh -i $HOME/.ssh/id_rsa -o StrictHostKeyChecking=no" --archive --compress --delete . username@ip:/path/to/place/build
And voila! We have set up everything we need. Now each time we push to the master, our Github Actions will run tests and deploy our project!
Here is 2 examples: with failed tests (build process didn't even start!) and with passed tests.
That's all!