From 31d774b751c129aad46ac1e9b5f1abf5e986994e Mon Sep 17 00:00:00 2001 From: danielvasic Date: Tue, 14 Apr 2026 12:41:24 +0200 Subject: [PATCH] init: hello-cicd project setup --- .gitea/workflows/ci.yml | 68 +++++++++++++++++++++++++++++++++++++++++ Dockerfile | 14 +++++++++ k8s/deployment.yaml | 29 ++++++++++++++++++ k8s/service.yaml | 13 ++++++++ main.py | 17 +++++++++++ requirements.txt | 2 ++ 6 files changed, 143 insertions(+) create mode 100644 .gitea/workflows/ci.yml create mode 100644 Dockerfile create mode 100644 k8s/deployment.yaml create mode 100644 k8s/service.yaml create mode 100644 main.py create mode 100644 requirements.txt diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..26af12e --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,68 @@ +# .gitea/workflows/ci.yml +name: CI/CD Pipeline + +on: + push: + branches: [main] + +env: + REGISTRY: git.fpmoz.sum.ba + IMAGE: git.fpmoz.sum.ba/${{ github.repository }} + +jobs: + # ── JOB 1: Build i Push Docker image ────────────────── + build: + runs-on: ubuntu-latest + steps: + - name: Checkout koda + uses: actions/checkout@v4 + + - name: Login u Gitea registry + run: | + echo ${{ secrets.REGISTRY_PASS }} | \ + docker login $REGISTRY \ + -u ${{ secrets.REGISTRY_USER }} --stdin + + - name: Build i Push image + run: | + TAG=${{ github.sha }} + docker build -t $IMAGE:$TAG -t $IMAGE:latest . + docker push $IMAGE:$TAG + docker push $IMAGE:latest + echo $TAG > tag.txt + + - name: Spremi image tag + uses: actions/upload-artifact@v4 + with: + name: image-tag + path: tag.txt + + # ── JOB 2: Deploy na k3s ─────────────────────────────── + deploy: + needs: build + runs-on: ubuntu-latest + steps: + - name: Checkout koda + uses: actions/checkout@v4 + + - name: Preuzmi image tag + uses: actions/download-artifact@v4 + with: + name: image-tag + + - name: Postavi kubeconfig + run: | + mkdir -p ~/.kube + echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > ~/.kube/config + chmod 600 ~/.kube/config + + - name: Update image tag u manifestu + run: | + TAG=$(cat tag.txt) + sed -i "s|image:.*|image: $IMAGE:$TAG|" k8s/deployment.yaml + + - name: Deploy na k3s + run: | + kubectl apply -f k8s/ + kubectl rollout status deployment/hello-cicd \ + -n student-${{ github.actor }} --timeout=120s diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6e5d318 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +# Dockerfile +FROM python:3.12-slim + +WORKDIR /app + +# Kopiraj requirements PRIJE koda — cache trick! +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +ENV APP_VERSION=dev +EXPOSE 8000 +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 0000000..0aef187 --- /dev/null +++ b/k8s/deployment.yaml @@ -0,0 +1,29 @@ +# k8s/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: hello-cicd + namespace: student-dvasic +spec: + replicas: 1 + selector: + matchLabels: + app: hello-cicd + template: + metadata: + labels: + app: hello-cicd + spec: + imagePullSecrets: + - name: gitea-creds + containers: + - name: hello-cicd + image: git.fpmoz.sum.ba/dvasic/hello-cicd:latest + ports: + - containerPort: 8000 + env: + - name: APP_VERSION + value: "latest" + resources: + requests: {cpu: 50m, memory: 64Mi} + limits: {cpu: 200m, memory: 128Mi} diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 0000000..d0dbdf4 --- /dev/null +++ b/k8s/service.yaml @@ -0,0 +1,13 @@ +# k8s/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: hello-cicd-svc + namespace: student-dvasic +spec: + selector: + app: hello-cicd + ports: + - port: 80 + targetPort: 8000 + type: NodePort diff --git a/main.py b/main.py new file mode 100644 index 0000000..4d5e4a2 --- /dev/null +++ b/main.py @@ -0,0 +1,17 @@ +# main.py +from fastapi import FastAPI +import os, datetime + +app = FastAPI() + +@app.get("/health") +def health(): + return { + "status": "ok", + "version": os.getenv("APP_VERSION", "dev"), + "timestamp": datetime.datetime.utcnow().isoformat() + } + +@app.get("/") +def root(): + return {"poruka": "Zdravo s k3s!", "host": os.uname().nodename} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6d4d13b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +fastapi==0.115.0 +uvicorn==0.32.0