Guide or Assistance On Setting Up CI/CD With GitHub Actions To My Linode
I am looking for either a guide/how-to or some assitance in setting up CI/CD to my Linode with GitHub Actions.
I have a NodeJS project on GitHub that I would like to have updated on my Linode any time I push updates to my main branch without me having to SSH into the machine and manually running a git pull on the production branch. The CI/CD needs to pull down the updated code, update/install any added/updated NodeJS packages, build the production code, and then restart it via PM2.
Thanks for any information that can be provided for me!
2 Replies
Hey Demonicpagan,
That's a solid workload which you've outlined here, and it's really pleasant to be able to automate things to this extent. I don't know anything really about GitHub's Actions product, but I have a hunch that you might be able to get away without building a full CI/CD pipeline. Please read on to find my recommendation of how you might just create a git remote
and a webhook. I hope this does the trick for you :]
Here is the outline:
- initialize a new bare repository on the server
- create a webhook to checkout, update, build, deploy, and restart
- add the new remote URL
- On the Linode you'll want to create a new bare repository.
$ mkdir node-project.git && cd node-project.git
$ git init --bare
Initialized empty Git repository in /home/Demonicpagan/node-project.git/
You also need to create a GIT_WORK_TREE
directory, and a deployment directory. Feel free to modify the content of these examples as needed, of course.
$ mkdir /opt/node-project-work-tree/
$ mkdir /opt/node-project/
2 . Next we are dealing with 43 lines of bash which take care of your 5 tasks. I've modified a file listed in the references to include some bug fixes and comments. You can put this file in /home/Demonicpagan/node-project.git/hooks/post-receive
. Touch it and set it as executable with chmod +x.
$ touch hooks/post-receive
$ chmod +x hooks/post-receive
Here are its contents. Be sure to change the values at the top of the file to correspond to your actual stuff.
#!/bin/bash
PROJECT=node-project
TARGET=/opt/node-project-work-tree/
DEPLOY=/opt/node-project/
GIT_DIR=/home/Demonicpagan/node-project.git/
BRANCH="main"
while read -r _ newrev ref
do
# only pulling the updated code on the main branch
if [ "$ref" = "refs/heads/$BRANCH" ];
then
# get the file list to check for packages
filelist=$(git diff-tree --no-commit-id --name-only -r "$newrev")
# check out the files to the working tree
echo "Ref $ref received. Deploying ${BRANCH} branch to production..."
git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH
cd $TARGET || exit 1
# if the package files have been changed
# then we are reinstalling
if [[ $filelist == *"package.json"* || $filelist == *"package-lock.json"* ]];
then
echo "Changes detected in Package files..."
echo "Reinstalling dependencies..."
npm i --only=prod
fi
# we are building and deploying in any case
echo "Building UI..."
npm run build
echo "Redeploying UI..."
rm -rf ${DEPLOY:?}/*
cp -r $TARGET/build/* $DEPLOY/
# restart with PM2
pm2 restart $PROJECT
else
echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
fi
done
3 . Lastly on your home machine you add the remote that you have created on the Linode platform, and push your project.
$ git remote add linode Demonicpagan@example.org:node-project.git/
$ git push linode +main:refs/heads/main
From then on, deployment from your home machine would consist of one command.
$ git push linode
…and that's that! I hope this outline for a git remote serves your needs.
References:
Thank you for this. I'm looking at what you have provided and seeing what I can make of it to use it. There are a few changes I needed to make for the shell script as I use yarn and not npm and building places what things in a dist folder that I will be running the project from.
I have been trying to figure out why my post-recieve
hook is not firing. Here is the contents of that file. I don't know where the error is, but it is never entering the while loop.
My repo since I want to not push directly to my Linode and host my repo on GitHub, I did a checkout and the repo lives in /home/demonicpagan/DexcomMongoBackup
. I have a webhook written in NodeJS that should run the post-receive
hook, but at the moment is a moot point since the hook isn't firing.
#!/bin/bash
# for debugging
set -ex
PROJECT=DexcomBackup
TARGET="/home/demonicpagan/DexcomMongoBackup"
GIT_DIR="/home/demonicpagan/DexcomMongoBackup/.git"
BRANCH="main"
while read -r _ newrev ref
do
echo "I ENTERED DO WHILE LOOP"
# only pulling the updated code on the main branch
if [ "$ref" = "refs/heads/$BRANCH" ]; then
echo "REF: $ref"
# get the file list to check for packages
filelist=$(git diff-tree --no-commit-id --name-only -r "$newrev")
# check out the files to the working tree
echo "Ref $ref received. Deploying ${BRANCH} branch to production..."
git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH
cd $TARGET || exit 1
# if the package files have been changed
# then we are reinstalling
if [[ $filelist == *"package.json"* || $filelist == *"yarn.lock"* ]]; then
echo "Changes detected in Package files..."
echo "Reinstalling dependencies..."
yarn --production=true
fi
# we are building and deploying in any case
echo "Rebuilding Bot..."
yarn clean
yarn build
echo "Redeploying Bot..."
# restart with PM2
pm2 restart $PROJECT
else
echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
fi
done