GitHub Actions CI/CD Tutorial Series — Part 3

--

tutorial banner

In Part 2 of this tutorial series, we covered the following steps:

*) Used of CNAME
*) Enabled SSL certificates for subdomains
*) Installed Docker

If you missed Part 2, you can find it here: Part 2

Check out Repo

In order to follow along, fork my GitHub Repo and check out the branch start-project-v1:

fork this project

You find the fork symbol on the top right side

fork project

IMPORTANT

Make sure you check out my Medium article: Kotlin Spring Boot Tutorial Part 3: Creating REST endpoints for a task app or my YouTube video: Kotlin Spring Boot Tutorial - Part 13 | application.yml Secrets about how to set up environments variables in IntelliJ IDE. When you have successfully set up everything then run the app.

Create the Dockerfile — Yalla | يلا

Now when you have opened the app in your IDE, create in the root folder the Dockerfile .

create Dockerfile in the root folder
create Dockerfile in the root folder

Remember that a Dockerfile doesn’t have a type at the end.

Add these lines to your Docker app:

# Use a specific OpenJDK version
FROM openjdk:20-slim as builder

# Set the working directory
WORKDIR /build

# Copy the files from the current directory to the working directory
COPY . .

# Build the application
RUN ./gradlew build

# Use a specific OpenJDK version for the runtime image
FROM openjdk:20-slim

# Create a new user and group for better security
RUN groupadd -r app && useradd --no-log-init -r -g app app

# Set the working directory
WORKDIR /app

Now, in your IntelliJ IDE navigate to build -> libs :

build -> libs -> jar

When you have pressed the play button for your app there should be a JAR file in your build -> libs folder. If the app doesn’t start make sure you read the IMPORTANT part from above, you also will need your supabase.com credentials.

If there is no JAR file then first build your project and then run your project:

build and run

Because we need to reference this “cicd-tutorial-0.0.1-SNAPSHOT.jar” in the next lines of your Dockerfile :

# Copy the compiled JAR file from the builder stage
COPY --from=builder /build/build/libs/cicd-tutorial-0.0.1-SNAPSHOT.jar task-app-api.jar

Here we rename “cicd-tutorial-0.0.1-SNAPSHOT.jar” to “task-app-api.jar” when copying the JAR file.

IMPORTANT even though you might see the file has “-plain” before the dot in build -> libs remove the ”-plain” and just name it “cicd-tutorial-0.0.1-SNAPSHOT.jar

The next lines are:

# Use the created user
USER app

# Set the entrypoint command
ENTRYPOINT ["java", "-jar", "task-app-api.jar"]

And for reference, this is the complete Dockerfile:

# Use a specific OpenJDK version
FROM openjdk:20-slim as builder

# Set the working directory
WORKDIR /build

# Copy the files from the current directory to the working directory
COPY . .

# Build the application
RUN ./gradlew build

# Use a specific OpenJDK version for the runtime image
FROM openjdk:20-slim

# Create a new user and group for better security
RUN groupadd -r app && useradd --no-log-init -r -g app app

# Set the working directory
WORKDIR /app

# Copy the compiled JAR file from the builder stage
COPY --from=builder /build/build/libs/cicd-tutorial-0.0.1-SNAPSHOT.jar task-app-api.jar

# Use the created user
USER app

# Set the entrypoint command
ENTRYPOINT ["java", "-jar", "task-app-api.jar"]

GitHub Actions CI/CD Pipeline

Now in order for the GitHub Actions CI/CD Pipeline to work we need to create two new folders in our project.

Because the GitHub Actions Pipeline will look for a folder in your project named .github

create new folder
.github directory
project overview

After you have created the directory .github you need to create another directory inside of .github and name it workflows because continuous integration and continuous deployment (CI/CD) are a workflow.

workflows directory

IMPORTANT it is really necessary that you name your directories exactly like that otherwise the CI/CD will not work.

Inside workflows create a YAML file and name it cicd.yml

YAML file for pipeline

Then give your workflow a name like “Build & Deployment” and add that it should trigger for push and pull-request events for the master branch.

name: Build & Deployment

on:
push:
branches:
- master
pull_request:
branches:
- master

After that add the jobs section the first job will be to build the project and because our Ubuntu instance is 22.04 we should also define the job that should run in Ubuntu 22.04.

jobs:
build:
name: Build Project
runs-on: ubuntu-22.04

Next, you can add the first steps for your build job. The first step will be to get a Slack notification when the Pipeline has started. You can give each step a name and then decide which action to use.

  steps:
- name: Slack Notification Ci/Cd started
uses: 8398a7/action-slack@v3.15.1
with:
status: ${{ job.status }}
fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
text: 'CI/CD started :eyes: In the Name of God the Merciful, the Compassionate / Bismillahir Rahmanir Raheem /بسم الله الرحمن الرحيم'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

In this code snippet, a GitHub Actions workflow step is defined to send a Slack notification when the CI/CD process starts. Here’s a breakdown of the step:

  1. name: The name of the step, which is "Slack Notification Ci/Cd started".
  2. uses: Specifies the GitHub Actions action to be used, in this case, 8398a7/action-slack@v3, a popular Slack notification action.
  3. with: This section defines the input parameters for the action:
  • status: The status of the job, which is dynamically set using ${{ job.status }}.
  • fields: A list of fields to be included in the Slack message, such as repository, commit message, author, etc.
  • text: The custom text message to be sent as a Slack notification, which includes a phrase in Arabic to signify the beginning of the CI/CD process.

4. env: This section defines the environment variables for the action:

  • SLACK_WEBHOOK_URL: The Slack webhook URL, which is stored as a secret in the repository settings, allows the action to send notifications to the specified Slack channel.

When the workflow reaches this step, a Slack notification will be sent to the configured channel with the specified message and fields. This helps you maybe your team informed about the status of the CI/CD pipeline and allows you to track the progress in real-time.

Set up Slack

Now open your Slack app or download it from https://slack.com/ .

First Create a new channel by clicking on “+ Add channels

create a new channel

Second, give your channel a name and click on “Create”

create channel

Go to “Settings & administration” -> “Manage apps

Slack app

On the top right corner, you will find the button “Build” and click on it.

click on Build

Then click on “Create an App

click on Create an App

Select next “From scratch

Then give it an app name and select your workspace and click on “Create App”.

create app

Then you should see the “Basic Information” side and select there “Incoming Webhooks”.

select Incoming Webhooks

Toggle the “On” button at “Incoming Webhooks”.

toggle On

Scroll down and click on “Add New Webhook to Workspace

click on Add New Webhook to Workspace

After that select your channel “cicd-pipeline” and click on “Allow

select your channel

In your Slack channel you should see something like this:

channel integration

From the Slack settings web page copy the curl command

copy curl command

Paste it in your terminal and press enter:

paste command in terminal

Then jump to your Slack channel again:

Hello World message

Create your first GitHub Secret

Below our curl command copy “Webhook URL

copy Webhook URL

Jump back to your GitHub Repo (Make sure you forked my repo: https://github.com/habibicoding/cicd-tutorial-mediumcom) go to “Settings

click Settings

Click on “Secrets and variables” and select “Actions

select Actions

Then click on “New repository secret

click on New repository secret

Because we have defined our slack secret in our cicd.yml as ${{ secrest.SLACK_WEBHOOK_URL }} we need to name it as SLACK_WEBHOOK_URL and past the Webhook URL from the Slack settings webpage and click on “Add secret”.

add a new secret
Secrets overview

With that, we conclude the third part of this tutorial series. If you found it useful and informative, give it a clap. Here is Part 4.

Don’t forget to check out the video version of this article on our YouTube channel at https://www.youtube.com/@habibicoding.

--

--