Introduction
Continuous Integration and Continuous Deployment (CI/CD) are essential practices in modern software development, allowing teams to deliver high-quality software quickly and efficiently. In this blog, we'll explore how to set up a robust CI/CD pipeline using GitHub Actions and Argo CD.
Project GitHub link
Learn how to deploy same Application without CI/CD on kubernetes
Deploy direct on kubernetes without CI/CD
When you use ArgoCD, then you don't have to deploy it manually.
Prerequisites
Before we dive in, make sure you have the following:
A GitHub account
A Kubernetes cluster
Basic knowledge of Kubernetes and Docker
Setting Up GitHub Actions
Creating a Workflow File
GitHub Actions allows you to automate your development workflows. To set up a CI pipeline, create a new directory called .github/workflows
in your repository. Inside this directory, create a file named githubAction.yaml.
name: build and push docker image
on:
push
jobs:
release-docker:
name: Release docker image
if: "!contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Get git SHA short
id: vars
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: GoalApp-CICD/
push: true
tags: |
anish60/app:latest
anish60/app:sha-${{ env.sha_short }}
labels: |
org.opencontainers.image.source=${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
- name: Generate deploy manifest from Jinja template
uses: cuchi/jinja2-action@v1.1.0
with:
template: GoalApp-CICD/Jinja-Template/deploy.yaml
output_file: GoalApp-CICD/Manifest/new-deploy.yaml
strict: true
variables: |
image_deploy_tag=sha-${{ env.sha_short }}
- name: Configure git for the action
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
- name: Stash unstaged changes
run: git stash --include-untracked
- name: Pull latest changes from the remote branch
run: git pull origin main --rebase
- name: Apply stashed changes
run: git stash pop || echo "No stashed changes to apply"
- name: Commit deploy manifest on local repo
run: |
git add GoalApp-CICD/Manifest/new-deploy.yaml
git commit -s -m "[skip ci] Generate deployment manifests"
- name: Push deploy manifests to remote repo
uses: ad-m/github-push-action@v0.6.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: main
This YAML pipeline is a GitHub Actions workflow designed to build and push a Docker image to Docker Hub when there is a push to the repository. Here's a step-by-step explanation of the pipeline:
Explanation of Workflow
Name and Trigger
name: build and push docker image
on:
push
name: The name of the workflow is "build and push docker image".
on: The workflow is triggered by a push event to the repository.
Jobs
jobs:
release-docker:
name: Release docker image
if: "!contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ubuntu-20.04
release-docker: This defines a job named "Release docker image".
if: This condition ensures the job runs only if the latest commit message does not contain
[skip ci]
.runs-on: The job runs on an
ubuntu-20.04
runner.
Steps
Checkout the repository
- name: Checkout uses: actions/checkout@v4
name: Checkout
uses: Uses the
actions/checkout
action to checkout the repository.
Set up Docker Buildx
- name: Set up Docker Buildx uses: docker/setup-buildx-action@v2
name: Set up Docker Buildx
uses: Uses the
docker/setup-buildx-action
action to set up Docker Buildx, which allows for advanced features like multi-platform builds.
Log in to Docker Hub
- name: Log in to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }}
name: Log in to Docker Hub
uses: Uses the
docker/login-action
to log in to Docker Hub with credentials stored in GitHub secrets.
Get git SHA short
- name: Get git SHA short id: vars run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
name: Get git SHA short
id: vars
run: Runs a shell command to get the short SHA of the latest commit and sets it as an environment variable.
Build and push Docker image
- name: Build and push Docker image uses: docker/build-push-action@v4 with: context: GoalApp-CICD/ push: true tags: | anish60/app:latest anish60/app:sha-${{ env.sha_short }} labels: | org.opencontainers.image.source=${{ github.repository }} org.opencontainers.image.revision=${{ github.sha }}
name: Build and push Docker image
uses: Uses the
docker/build-push-action
to build and push the Docker image.with: Specifies the context, push flag, tags, and labels for the Docker image.
Generate deploy manifest from Jinja template
- name: Generate deploy manifest from Jinja template uses: cuchi/jinja2-action@v1.1.0 with: template: GoalApp-CICD/Jinja-Template/deploy.yaml output_file: GoalApp-CICD/Manifest/new-deploy.yaml strict: true variables: | image_deploy_tag=sha-${{ env.sha_short }}
name: Generate deploy manifest from Jinja template
uses: Uses the
cuchi/jinja2-action
to generate a deployment manifest from a Jinja template.with: Specifies the template file, output file, and variables to be used in the template.
Configure git for the action
- name: Configure git for the action run: | git config --local user.email "action@github.com" git config --local user.name "GitHub Action"
name: Configure git for the action
run: Configures git with a local user name and email for committing changes.
Stash unstaged changes
- name: Stash unstaged changes run: git stash --include-untracked
name: Stash unstaged changes
run: Stashes any unstaged changes including untracked files.
Pull latest changes from the remote branch
- name: Pull latest changes from the remote branch run: git pull origin main --rebase
name: Pull latest changes from the remote branch
run: Pulls the latest changes from the
main
branch with rebase.
Apply stashed changes
- name: Apply stashed changes run: git stash pop || echo "No stashed changes to apply"
name: Apply stashed changes
run: Applies the stashed changes or prints a message if there are no stashed changes to apply.
Commit deploy manifest on local repo
- name: Commit deploy manifest on local repo run: | git add GoalApp-CICD/Manifest/new-deploy.yaml git commit -s -m "[skip ci] Generate deployment manifests"
name: Commit deploy manifest on local repo
run: Adds and commits the newly generated deployment manifest with a commit message that includes
[skip ci]
to prevent triggering another CI run.
Push deploy manifests to remote repo
- name: Push deploy manifests to remote repo uses: ad-m/github-push-action@v0.6.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} branch: main
name: Push deploy manifests to remote repo
uses: Uses the
ad-m/github-push-action
to push the changes to the remotemain
branch.with: Specifies the GitHub token and branch to push to.
This workflow automates the process of building and pushing Docker images, generating deployment manifests, and pushing these manifests back to the repository, ensuring the deployment process is seamless and consistent.
Configuring the Docker username and password as secret in the Github
Go to the
Setting
in your RepoThen , on the Left you have
Secret and Variable
section. Under that you haveAction
section. Click on that you will see-
I have already configured here , In your case click on
New repository secret
and configure the username and password for docker hub.
Installing Argo CD
Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. To install Argo CD, run the following commands:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
kubectl get secret -n argocd argocd-initial-admin-secret -oyaml
You will get the LoadBalancer Ip of the ArgoServer . So , paste to browser . You will get admin page.
Username : admin
Password : <decoded secret>
Decode the secret using echo "<secret-key>" | base64 --decode.
Connecting Argo CD to Your GitHub Repository
To connect Argo CD to your GitHub repository, follow these steps:
Access the Argo CD UI (port-forward or load balancer).
After running command, you will get the LoadBalancer Ip and via which you can access UI.
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
Log in using the default admin credentials.
kubectl get secret -n argocd argocd-initial-admin-secret -oyaml
Decode the secret using
echo "<secret-key>" | base64 --decode
Username :
admin
Password :<decoded secret>
Create a new application in Argo CD, specifying your GitHub repository and the path to your Kubernetes manifests.
In my case the the directory that ArgoCd is monitoring is
GoalApp-CICD/Manifest
Once you are done with creating the Application in ArgoCd then i will automatically fetch all the manifest file and deployed to Kubernetes cluster.
Conclusion
In this guide, we've set up a complete CI/CD pipeline using GitHub Actions and Argo CD. This setup allows you to automate your build, test, and deployment processes, ensuring that your applications are always up-to-date and running smoothly