Development

Automatic Deployment with GitHub on Any Server Instance without GitHub workflow or SSH


Learn to impliment automatic deployment an application to the cloud virtual server without using GitHub workflow and SHH, by means of a nodejs based express server.

Automatic Deployment with GitHub on Any Server Instance without GitHub workflow or SSH

A guide on how to deploy an application on any kind of virtual server instance without the use of SSH and GitHub actions.

This article aims to propose a solution for those who are using virtual servers to host their sites, servers, etc. The main goal is to explain and show how one would deploy their application on any kind of virtual server instance without the use of SSH and GitHub actions.

Deploying a site via ssh through GitHub actions or workflow can be tricky and complicated sometimes, Recently I was going through something and was unable to figure out a way to deploy my application to the server via my GitHub, and every time I had to pull the build to my server manually to update the changes I had, which is very time consuming and not efficient so I had to do come up with a solution

The Solution I come up with is a hook based approach, every repo has these hooks available, meaning that I can set up a listener to listen for the webhook trigger and perform whatever action I want, in my case, I performed a git pull from a branch and make a build directly on my server.

Okay enough with the theory, let's see this in action:

Step 1:

Make sure to install Node.js on your virtual server whether it is hosted on GCP or Amazon, in my case I used nvm and installed Node.js version 14 since my application was built on Node.js version 14.

Step 2:

Make sure to give your virtual server a public IP and expose a port. I was using GCP so therefore in my cloud console, in the firewall section, I had to enable a port 8080. And inside of my server sudo ufw allow 8080 to allow this port locally as well.

Step 3:

Testing the port, check if the port is really working or not. You can use an online solution like this one Port Checker — Check Open Ports Online. Or You can check it manually. To Check manually you need to write *nc -l -p 8080 -t on the server terminal and echo “123” | nc -t <public ip here> 8080 *on your local mac terminal. If you get a response on your server 123, that means your port is accessible via the internet and you are good to go.

Step 4:

Setting up a webhook, In your repo’s settings page, there is a tab name webhook.

And you need to add a webhook with the following settings

And in the **Let me select individual events **section, kindly check Pull Requests. Once that is done save your settings.

What we have done is set up a webhook, that will trigger on every pull request. So let's say you have one stagging branch and one main branch. Whenever you make a pull request from stagging branch to the main branch, and you merge it, the webhook will trigger with these params action => “closed” head => “develop” merged => true base => “master”

Where the head is basically the branch the pull is from and the base is the branch where it will get merged, and action is something to indicate that the pull request is merged.

Step 5:

The Next Step would be creating a simple yet effective micro Node.js express server, that will stay alive by means of PM2.

Go to the server location where your file needed to be deployed and cd a directory back. Create a folder name with AD automatic deployment

mkdir AD
cd AD

and npm init, this will generate a package.json for you. Very next step would be now to create an index.js file by typing nano index.js, and it will open up a text editor where you can paste the below code.

const express = require('express') const fs = require('fs') const {
    exec
} = require("child_process");
const app = express() const port = 8080 app.use(express.json()) app.post('/', (req, res) => {
    const {
        body
    } = req
    const merged = body.pull_request.merged
    const status = body.action
    const head = body.pull_request.head.ref
    const base = body.pull_request.base.ref console.log({
        merged,
        status,
        head,
        base
    }) if (status === "closed" && head === "develop" && merged === true && base === "master") {
        exec("cd ../ws/ && git stash && git pull origin develop --no-edit && make", (error, stdout, $
            if (error) {
                console.log(`error: ${error.message}`);
                return;
            }
            if (stderr) {
                console.log(`stderr: ${stderr}`);
               return 
        });
        res.send('Hello World!')
    } else {
        res.send('Hello World!')
    }
})
app.get('/', (req, res) => {
    // const head = req.body.head.ref
    // const status = req.body.status
    // console.log({head,status})
    res.send('Hello Worlds!')
})
app.listen(port, () => {
            console.log(`Example app listening at [http://localhost:${port}`](http://localhost:${port}`))

The above code is pretty self-explanatory, we have the express module installed. And we exposed two endpoints, a Get and a Post request on route “/”. After that we a condition matching, if the pull request is from our desire branch into our desire branch and the action that happened, was merged and closed. and once the condition has been matched exec a shell command, in my case I already had a clone branch in my server with node modules installed and I just wanted to run the following command.

cd ../ws/ && git stash && git pull origin main — no-edit && npm i && make

the above command navigates to my desired location, stash any existing changes on the server, pull from the main branch with no-edit options, and then in the last makes a build. the build will be generated and will be placed into your desired branch, you can change the build settings on your own code, if you have React app, webpack output change would do the trick for you. if you are using pm2 and have a node server that requires changes, pm2 restart would require after you replace all the code. You can modify it as you wish, but the concept is to pull from my branch and install node modules and make a build via terminal.

Step 6:

Now we have our code in place, we need to run it, to test it you can just type node index.js and from the browser access http://yourip:8080/, You should see a response of Hello World, that indicate everything is fine and working.

You can test the post request by just creating a pull request from stagging to the main branch which is the production branch, you will be able to spot the changes in the logs.

If you want to run your Node.js app silently in the background you can install pm2.

npm i pm2 -g
pm2 start index.js

This will install pm2 and start it silently in the background. To Access the logs from you can write

pm2 log index

To look at the logs of our micro application.

If you have read through this article props to you and thank you and I hope the concept is pretty clear.

You can follow me at https://rajaosama.me/ and on GitHub via https://github.com/raja0sama.

Thank you.

Author Image

Raja Osama

I Describe Myself as a Polyglot ~ Tech Agnostic ~ Rockstar Software Engineer. I Specialise in Javascript-based tech stack to create fascinating applications.

I am also open for freelance work, and in-case you want to hire me, you can contact me at rajaosama.me@gmail.com or contact@rajaosama.me