Codementor Events

Automating your routine with Github Actions

Published Feb 12, 2022Last updated Aug 10, 2022
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:
Screenshot 2022-02-12 at 02.43.14.png

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.
project structure
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.
Failed Tests
All is well

That's all!

automation joke.jpeg

Thank you for reading! Welcome to the comment sections for question and suggestions!

Discover and read more posts from Sam Bocharov
get started
post commentsBe the first to share your opinion
Show more replies