How I achieved Continuous Deployment (CD) with just a shell script?

How I achieved Continuous Deployment (CD) with just a shell script?

Continuous deployment (CD) is a simple two step process:

  • Take the code from a repository (e.g A Git repository)
  • Deploy it on server

We were using CD to automate the deployment of apps on our development servers, so that as soon as a developer pushes code to Git, they can see their changes right away. Every QA task, including unit tests and integration tests, comes after that.

Previously, we were using Jenkins to achieve this. Jenkins, is no matter one of the most popular and free CI/CD tools available out there. But if something is popular, does that mean we also need it ?

Popularity alone does not dictate suitability or effectiveness in meeting the specific needs and requirements of an organization or project. Choosing the right tool, whether it's Jenkins or something else, depends on various factors including but not limited to the size of project, how complicated it is, which technology is being used, and which features are required.

What's wrong with Jenkins ?

Please keep in mind that the purpose of this post is not to discredit Jenkins as a tool. But since I personally prioritize problem-solving skills and foundational knowledge over tools adoption, I consistently seek ways to improve processes in the most resource-efficient manner possible.

Jenkins has plugins for different jobs it can do. These plugins make Jenkins really flexible, so it can handle lots of different tasks. But having lots of plugins also means increased attack surface. So, while plugins give Jenkins more abilities, they also make it more vulnerable to attacks.

Plugins are helpful if we are doing CI tasks, since for each CI task, we can utilize a plugin of our choice. But whole flexibility of Jenkins became a headache, when we talk about CD using Jenkins.

Considering the simple CD scenario which I explained in the start of this article, why do I need to install a bunch of plugins likes these:

The Shell Script:

Once I figured out that achieving the desired behavior with Jenkins was more complex than anticipated, I decided to pull out the beast—the shell script.

This shell script not only performs the tasks required, but it also posts the message in relevant slack channel of our space, once the deployment goes successful.

Below is the image of a message posted in slack channel by my shell script.

How it works?

I have explained the workflow in a diagram, which can be seen at this LINK. However, in order to preserve confidentiality, I will not be able to post the whole shell script here. Apologies in advance.

Clicking on the image will take you to the MIRO board website, where you can zoom in and out to view the diagram better.

Once you finished looking at the diagram above, skim through the following points to get a higher level understanding of script's working:

  • it first traverse through all the project directories and compare the local code with the code in remote repository. Script utilizes "Git polling" to achieve this behavior. Once it found that local branch is behind the remote branch, it pulls latest changes, and did all the deployment steps.
  • Once the deployment is finished, script posts the success message in the project's specific slack channel. If there is an error, it posts the error message in channel.

Slack Integration:

In order to integrate my shell script with slack, I first created a custom slack app named "DevOps Bot" and integrated it with all the slack channels. Then I get webhook for each channel and utilize the curl command inside the script to make a POST request to respective channel. The function responsible for sending slack message can be seen below:

send_slack_message() {
  local webhook_url=$1
  local message=$2

  payload=$(cat <<EOF
{
  "text": "${message}"
}
EOF
  )

  curl -X POST -H 'Content-type: application/json' --data "${payload}" ${webhook_url}
}        

The above function is called like this:

LATEST_COMMIT=$(git log -1)
part1="[Deployed to Dev] Build successful for ${project_dir%/}'s UI. Latest commit:"
part2=""\`\`\`${LATEST_COMMIT}\`\`\`""
message="${part1}${part2}"
send_slack_message "$slack_hook" "$message"        

where $slack_hook is the webhook of the respective channel and $message is the message to be posted in the channel.

Three backticks ``` are used to format the 'Latest commit' as a code block inside slack channel.

Conclusion:

Remember, the goal is to solve problem while saving as much resources as possible and utilizing tools and practices that minimize waste and maximize productivity.

I believe that by prioritizing foundational knowledge, we can create more robust and flexible solutions, enabling us to tackle complex challenges with confidence and innovate beyond the limitations of any single tool.

Muhammad Ateeb Aslam

DevOps Engineer | Certified in CyberSecurity (isc2) |

6mo

Wanted to thank Naufal Ali Shah for the motivation and support

Like
Reply
Babar Zahoor

Board Member KPITB | OpenRiyadh | Co-Founder and CTO at CloudDev Technologies | Founder OSFP | Digital Transformation | ex Systems Limited | ex Oxfam | ex BoD ISOC Pakistan | AI Cloud Architect

6mo

good work

To view or add a comment, sign in

Insights from the community

Others also viewed

Explore topics