In this tutorial, we will see how we can make a CI/CD (Continuous Integration and Continuous Delivery) script with GitHub Actions and a simple NestJS server.
Introduction
NestJS is a Framework for building Node.js server side application. It is built with TypeScript and use Express or Fastify HTTP server framework under the hood. It's architecture is heavily inspired by Angular. It integrates a lot of features and is very easy to use.
GitHub Actions is GitHub take on CI/CD. It allows you to automate your build process and deploy your code directly from your GitHub repository.
Goals
Our goal is to create a simple NestJS server with the Nest CLI, deploy it using ScaleDynamics cloud platform and then automate it with GitHub Actions. We'll learn how you can use GitHub Actions to deploy with the ScaleDynamics platform.
Prerequisites
To follow along, you will need:
- A GitHub account and a repository ready to be used with GitHub Actions.
- Knowledge of Git and have it installed on your machine.
- Node.js and yarn / npm installed. You can go here to download the latest version of Node.js and npm.
Creating the project
To create the project, we can use the Nest CLI or clone a project starter from GitHub:
npm i -g @nestjs/cli
nest new my-server
or
git clone https://github.com/nestjs/typescript-starter.git my-server
Move into the project folder:
cd my-server
You can test if the project is working locally by running:
npm run start
You can check you receive Hello World!
by running:
curl localhost:3000
Now that we saw the project working, we just need to make a change in the scripts of the package.json
file. When the server is deployed with ScaleDynamics, the server is started with the start
command. We will change it so it launch the server in production mode by default and not in dev mode.
// package.json
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"dev": "nest start",
"dev:watch": "nest start --watch",
"dev:debug": "nest start --debug --watch",
"start": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
Everything is ready to be deployed !
Account creation and ressource selection
To deploy this server on ScaleDynamics's cloud, you need an account and create an environment with a ressource for it. The cloud resource provides virtual CPU and storage capacities used to execute the app. In this tutorial we will use a free shared resource available on ScaleDynamics’s cloud. These are the best one for testing. In this tutorial we will see later how you can upgrade to a dedicated production resource on the public cloud provider and region of your choice.
If you don't have an account, feel free to create one here (it's free and no credit card are required). Once your account is created, sign in.
Let's create a project and an environment on the ScaleDynamics's console. Select your organization, create a new project, then create a new environmnent. Now we need to choose what kind of service we need for our deployment. There are four types:
- managed HTTP docker
- managed Node.js server
- managed Node.js module
- static assets hosting
For our NestJS server, we need a (surprise) server. Let's pick the managed Node.js server. You can learn more on the other types in the ScaleDynamics documentation.
Deployment
The environment is ready to run our application, let's deploy on it.
Configuration file
First, let's add a configuration to tell the SDK what type of application we want to deploy. At the root of the project, create a warp.config.js
file:
// warp.config.js
module.exports = {
server: "nest",
};
Build
Build the project to let Nest compile TypeScript and optimize and bundle everything for us:
yarn build
Login
Log into your account and select your organization via the prompt:
npx warp login
Deploy
Finally, we can run the deployment command:
npx warp deploy
This command will dump something like this:
You can see that a server was detected from your configuration file. Now follow the prompt, select the project you created, then the environment. The prompt will also ask you for a hostname, you can leave it blank for a random name or use the one you want. Finally, you can select a host.
The deployment will be done in a few minutes. At the end, the command will dump something like this:
You can now open test it by visiting the URL dumped or doing a curl request.
Automation with GitHub Actions
To simplify and automate this process, let's use GitHub Actions.
Create a GitHub repository
Before we can automate the process, you need to create a GitHub repository and upload the project there.
You can learn more about it on the GitHub documentation.
Define our workflow
Now let's think about what workflow we want to automate. Our final goal is to deploy our server, but before deploying, we need to check the quality of the code, test it, build the project and finally deploy it. For this example there will be four steps:
- Lint our code with ESLint
- Test our code with Jest
- Build our project
- Deploy it
The NestJS startup project we use got everything to do so.
Create the workflow
Let's create a new workflow by creating a new folder at the root of the project called .github
and an other folder inside called workflows
. Inside workflows
, create a main.yml
file and copy this code:
name: Deploy
# Controls when the workflow will run
on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
env:
# replace with your project/env name
ORG_PROJECT: nest-test
DEPLOY_ENV: dev
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Install dependencies</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">yarn</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Lint the codebase</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">yarn lint</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Test our code</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">yarn test</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Build</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">yarn build</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Login</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">npx warp login --api-key=${{ secrets.SD_API_KEY }}</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Deploy</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">npx warp deploy --project ${ORG_PROJECT} --env ${DEPLOY_ENV}</span>
API key for login
Your workflow is ready, but for the login step, we need an API key to authenticate with ScaleDynamics. This API key can be created on the ScaleDynamics console:
Once your API key is created, we can create a secret in your repository so we can use it in our workflow:
Test it
Now you can try it by going into the Actions tab on your repository and trigger the workflow:
The workflow will run and you will be able to see the job deploy
. Click on it and you can see all the steps that are executed. At the end if all go well you should have something like:
If there is an error along the way you will be able to easily spot it and fix it.
Go further
This was a simple example of setting up CI/CD to deploy an server with ScaleDynamics, but you can do way more things with it. For exemple, you could lint the code on every commit to ensure styling coherence and ensure no mistake are present in your codebase, or you could deploy you code in preproduction at every commit on a branch preprod
. The sky is the limit.
If you want to know more, I encourage you to read this JetBrains guide. It's related to their TeamCity CI/CD platform but they perfectly explain the principles and what you can do with CI/CD in general.
Enjoy !
Top comments (1)
npx warp deploy got succeeded but
I am getting this error. What to do?