Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/workflows/docker-pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# .github/workflows/ci-cd.yml

name: CI/CD Pipeline

# Trigger this workflow on every push or pull request to any branch
on:
push:
branches:
- 'feature'

jobs:
build-test-and-push:
runs-on: ubuntu-latest

steps:
# Step 1: Check out your source code so future steps can access it
- name: Checkout code
uses: actions/checkout@v4

# Step 2: Set up Docker Buildx for advanced builds (multi-platform support)
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

# Step 3: Log in to Docker Hub using secrets you store in your repo settings
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# Step 4: Build and push the Docker image with your versioned tag
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/devops:${{ github.sha }}

# Step 5: Update the image tag
- name: Update image tag in deployment manifest
run: |
sed -i "s|\(image: ${{ secrets.DOCKERHUB_USERNAME }}/devops:\).*|\1${{ github.sha }}|" deployment.yml

# Step 6: Commit and Push the updated manifest
- name: Commit updated manifest
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"
git add deployment.yml
git commit -m "Update image tag to ${{ github.sha }}"
git push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions Ansible/inventory
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
localhost ansible_connection=local
10 changes: 10 additions & 0 deletions Ansible/playbook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- name: Apply Kubernetes manifests using kubectl
hosts: localhost
become: true
tasks:
- name: Apply Deployment YAML
command: kubectl apply -f ../deployment.yml --kubeconfig=/etc/rancher/k3s/k3s.yaml

- name: Apply Service YAML
command: kubectl apply -f ../service.yml --kubeconfig=/etc/rancher/k3s/k3s.yaml

15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# base image that python has installed
FROM python:3.9-slim

WORKDIR /app

# Copying the app files into a container
COPY requirements.txt .
COPY helloapp/ helloapp/

RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 8080

# A command to run Gunicorn
CMD ["gunicorn", "--bind", "0.0.0.0:8080", "helloapp.app:app"]
25 changes: 9 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
# Formlabs DevOps home assignment
Technology choices and possible alternatives:

This repository contains a home assignment code for DevOps applicants for Formlabs.
- **Docker**: I used it because it allows me to package the application and all its dependencies into a portable image, ensuring it runs consistently across any environment.

See all open jobs at https://careers.formlabs.com/
Alternatives: Podman and Buildah offer similar functionality and can even be lighter since they do not require a running daemon. However, Docker remains the industry standard and is widely supported by CI/CD tools and cloud providers.

- **k3s**: I used k3s as my Kubernetes distribution because it’s a lightweight alternative to Minikube. It provides a full Kubernetes API while consuming fewer resources and booting up much faster, which is ideal for local development and fast CI testing.

## Task
- **Ansible**: Ansible is used to automate deployment and infrastructure tasks in a simple way where it's human-readable and idempotent also worth to note that it's Agentless (Doesn't require extra software) and works really well with both Docker and Kubernetes.

0. Fork this repo.
1. Create a deployable docker image for the application.
- Feel free to switch up technologies. For example you can use `buildah` instead of Docker.
2. Create a Kubernetes deployment and service for the application.
- Just aim for the simplest setup, no ingress deployment is needed. Feel free to use Helm.
- You can use [Minikube](https://minikube.sigs.k8s.io/docs/start/) or [k3s](https://k3s.io/) or any other Kubernetes distribution you are familiar with.
3. Create automation to build, test and deploy the application when a change happens in git.
- Feel free to switch up technologies. For example you can use an Ansible playbook or a Jenkins pipeline.
4. Send us the fork where you did your work.
Alternatives: Chef and Puppet but they use Ruby for (Chef) and DSLs for (Puppet) which is harder to read and write than Ansible.

### Notes
- **GitHub Actions**: I used it since it integrates directly with the repository that i have on Github and doesn't need to install or configure external CI/CD servers. Since Actions trigger automatically on Push events.

- Explain as much as possible in the commit message(s) and/or comments if needed. See more on commit messages [here](https://chris.beams.io/posts/git-commit/).
- It would be great if you'd also write about why you choose a certain technology if there are alternatives to consider.
Alternatives: Jenkins and GitLab CI; I haven't used Jenkins since it requires maintaining my own Jenkins server, plugins and agents.
As for GitLab CI, it's relaly strong especially for GitLab hosted projects, but I didn't need to use it here since my repo is available on GitHub.
21 changes: 21 additions & 0 deletions deployment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloapp-deployment
spec:
replicas: 2 # Number of app pods to run
selector:
matchLabels:
app: helloapp
template:
metadata:
labels:
app: helloapp # Pods will get this label for selector matching
spec:
containers:
- name: helloapp
image: heisenberg1420/devops:daff7b21c04b449ae87bc9f2b4ef6952e5b0ccc9
ports:
- containerPort: 8080
imagePullSecrets:
- name: regcred
13 changes: 13 additions & 0 deletions service.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: helloapp
spec:
type: NodePort # Exposes service on each Node's IP at a static port
selector:
app: helloapp # It will select this label to route traffic to pods
ports:
- protocol: TCP
port: 8081 # Port to access service inside the cluster
targetPort: 8080 # Port on which your pod's container listens