feat: Implement Helm Chart and update CI/CD pipeline
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
This commit is contained in:
@@ -50,33 +50,34 @@ jobs:
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# CD PART
|
||||
# CD PART (HELM)
|
||||
# -----------------------------------------------------------------
|
||||
- name: Install Kubectl Binary
|
||||
- name: Install Kubectl & Helm
|
||||
run: |
|
||||
# Install kubectl (ARM64)
|
||||
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl"
|
||||
chmod +x kubectl
|
||||
sudo mv kubectl /usr/local/bin/
|
||||
|
||||
# Install Helm
|
||||
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||||
|
||||
- name: Deploy to Kubernetes and Update
|
||||
- name: Deploy with Helm
|
||||
run: |
|
||||
# 1. Write Kubeconfig content to file
|
||||
echo "${{ secrets.KUBE_CONFIG }}" > /tmp/kubeconfig.yaml
|
||||
|
||||
# 2. Get the new image Digests
|
||||
BACKEND_DIGEST="${{ vars.GITEA_REGISTRY_URL }}/${{ github.repository }}/backend@${{ steps.docker_build_backend.outputs.digest }}"
|
||||
FRONTEND_DIGEST="${{ vars.GITEA_REGISTRY_URL }}/${{ github.repository }}/frontend@${{ steps.docker_build_frontend.outputs.digest }}"
|
||||
|
||||
# 3. Update Deployment
|
||||
kubectl set image deployment/evrak-backend backend=${BACKEND_DIGEST} \
|
||||
--kubeconfig=/tmp/kubeconfig.yaml -n default
|
||||
# 2. Deploy using Helm Upgrade
|
||||
# We pass the image repository and tag explicitly to ensure we use the Gitea registry
|
||||
helm upgrade --install evrak ./deploy/charts/evrak \
|
||||
--kubeconfig /tmp/kubeconfig.yaml \
|
||||
--namespace default \
|
||||
--set backend.image.repository=${{ vars.GITEA_REGISTRY_URL }}/${{ github.repository }}/backend \
|
||||
--set backend.image.tag=latest \
|
||||
--set frontend.image.repository=${{ vars.GITEA_REGISTRY_URL }}/${{ github.repository }}/frontend \
|
||||
--set frontend.image.tag=latest \
|
||||
--set postgres.auth.password=${{ secrets.DB_PASSWORD }}
|
||||
|
||||
kubectl set image deployment/evrak-frontend frontend=${FRONTEND_DIGEST} \
|
||||
--kubeconfig=/tmp/kubeconfig.yaml -n default
|
||||
|
||||
# 4. Rollout Restart to ensure fresh pods
|
||||
kubectl rollout restart deployment/evrak-backend \
|
||||
--kubeconfig=/tmp/kubeconfig.yaml -n default
|
||||
|
||||
kubectl rollout restart deployment/evrak-frontend \
|
||||
--kubeconfig=/tmp/kubeconfig.yaml -n default
|
||||
# 3. Force restart to pick up latest image if tag is 'latest' (Helm doesn't always redeploy if values didn't change)
|
||||
kubectl rollout restart deployment/evrak-backend --kubeconfig /tmp/kubeconfig.yaml -n default
|
||||
kubectl rollout restart deployment/evrak-frontend --kubeconfig /tmp/kubeconfig.yaml -n default
|
||||
|
||||
6
deploy/charts/evrak/Chart.yaml
Normal file
6
deploy/charts/evrak/Chart.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
apiVersion: v2
|
||||
name: evrak
|
||||
description: A Helm chart for Evrak Project Management System
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "0.1.0"
|
||||
43
deploy/charts/evrak/templates/_helpers.tpl
Normal file
43
deploy/charts/evrak/templates/_helpers.tpl
Normal file
@@ -0,0 +1,43 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "evrak.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
*/}}
|
||||
{{- define "evrak.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "evrak.labels" -}}
|
||||
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{ include "evrak.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "evrak.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "evrak.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
54
deploy/charts/evrak/templates/backend.yaml
Normal file
54
deploy/charts/evrak/templates/backend.yaml
Normal file
@@ -0,0 +1,54 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "evrak.fullname" . }}-backend
|
||||
labels:
|
||||
{{- include "evrak.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: backend
|
||||
spec:
|
||||
replicas: {{ .Values.backend.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "evrak.selectorLabels" . | nindent 6 }}
|
||||
app.kubernetes.io/component: backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "evrak.selectorLabels" . | nindent 8 }}
|
||||
app.kubernetes.io/component: backend
|
||||
spec:
|
||||
containers:
|
||||
- name: backend
|
||||
image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.backend.service.port }}
|
||||
env:
|
||||
- name: DB_HOST
|
||||
value: {{ include "evrak.fullname" . }}-postgres
|
||||
- name: DB_PORT
|
||||
value: {{ .Values.backend.env.dbPort | quote }}
|
||||
- name: DB_USERNAME
|
||||
value: {{ .Values.postgres.auth.username | quote }}
|
||||
- name: DB_DATABASE
|
||||
value: {{ .Values.postgres.auth.database | quote }}
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "evrak.fullname" . }}-db-secret
|
||||
key: password
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "evrak.fullname" . }}-backend
|
||||
labels:
|
||||
{{- include "evrak.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: backend
|
||||
spec:
|
||||
ports:
|
||||
- port: {{ .Values.backend.service.port }}
|
||||
targetPort: {{ .Values.backend.service.port }}
|
||||
selector:
|
||||
{{- include "evrak.selectorLabels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: backend
|
||||
40
deploy/charts/evrak/templates/frontend.yaml
Normal file
40
deploy/charts/evrak/templates/frontend.yaml
Normal file
@@ -0,0 +1,40 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "evrak.fullname" . }}-frontend
|
||||
labels:
|
||||
{{- include "evrak.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: frontend
|
||||
spec:
|
||||
replicas: {{ .Values.frontend.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "evrak.selectorLabels" . | nindent 6 }}
|
||||
app.kubernetes.io/component: frontend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "evrak.selectorLabels" . | nindent 8 }}
|
||||
app.kubernetes.io/component: frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: frontend
|
||||
image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.frontend.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.frontend.service.port }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "evrak.fullname" . }}-frontend
|
||||
labels:
|
||||
{{- include "evrak.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: frontend
|
||||
spec:
|
||||
ports:
|
||||
- port: {{ .Values.frontend.service.port }}
|
||||
targetPort: {{ .Values.frontend.service.port }}
|
||||
selector:
|
||||
{{- include "evrak.selectorLabels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: frontend
|
||||
32
deploy/charts/evrak/templates/ingress.yaml
Normal file
32
deploy/charts/evrak/templates/ingress.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ include "evrak.fullname" . }}
|
||||
labels:
|
||||
{{- include "evrak.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- with .Values.ingress.annotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
rules:
|
||||
- host: {{ .Values.global.domain }}
|
||||
http:
|
||||
paths:
|
||||
- path: /api
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "evrak.fullname" . }}-backend
|
||||
port:
|
||||
number: {{ .Values.backend.service.port }}
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "evrak.fullname" . }}-frontend
|
||||
port:
|
||||
number: {{ .Values.frontend.service.port }}
|
||||
{{- end }}
|
||||
70
deploy/charts/evrak/templates/postgres.yaml
Normal file
70
deploy/charts/evrak/templates/postgres.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "evrak.fullname" . }}-postgres
|
||||
labels:
|
||||
{{- include "evrak.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "evrak.selectorLabels" . | nindent 6 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "evrak.selectorLabels" . | nindent 8 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: "{{ .Values.postgres.image.repository }}:{{ .Values.postgres.image.tag }}"
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
value: {{ .Values.postgres.auth.username | quote }}
|
||||
- name: POSTGRES_DB
|
||||
value: {{ .Values.postgres.auth.database | quote }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "evrak.fullname" . }}-db-secret
|
||||
key: password
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/postgresql/data
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ include "evrak.fullname" . }}-postgres-pvc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "evrak.fullname" . }}-postgres
|
||||
labels:
|
||||
{{- include "evrak.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
spec:
|
||||
ports:
|
||||
- port: 5432
|
||||
targetPort: 5432
|
||||
selector:
|
||||
{{- include "evrak.selectorLabels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "evrak.fullname" . }}-postgres-pvc
|
||||
labels:
|
||||
{{- include "evrak.labels" . | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: {{ .Values.postgres.storage.className }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.postgres.storage.size }}
|
||||
13
deploy/charts/evrak/templates/secrets.yaml
Normal file
13
deploy/charts/evrak/templates/secrets.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "evrak.fullname" . }}-db-secret
|
||||
labels:
|
||||
{{- include "evrak.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
data:
|
||||
# In a real scenario, you'd want to generate this or pass it in.
|
||||
# For now, we'll use the value from values.yaml (base64 encoded automatically by Helm if we used stringData, but here we do it manually or let user provide it)
|
||||
# Better approach: use stringData
|
||||
stringData:
|
||||
password: {{ .Values.postgres.auth.password | default "postgres" | quote }}
|
||||
43
deploy/charts/evrak/values.yaml
Normal file
43
deploy/charts/evrak/values.yaml
Normal file
@@ -0,0 +1,43 @@
|
||||
global:
|
||||
domain: evrak.konstantiniyye.studio
|
||||
|
||||
backend:
|
||||
image:
|
||||
repository: git.konstantiniyye.studio/muhammed/evrak/backend
|
||||
tag: latest
|
||||
pullPolicy: Always
|
||||
replicas: 1
|
||||
service:
|
||||
port: 3000
|
||||
env:
|
||||
dbPort: 5432
|
||||
dbDatabase: evrak
|
||||
# dbHost, dbUsername, dbPassword will be injected via secrets/templates
|
||||
|
||||
frontend:
|
||||
image:
|
||||
repository: git.konstantiniyye.studio/muhammed/evrak/frontend
|
||||
tag: latest
|
||||
pullPolicy: Always
|
||||
replicas: 1
|
||||
service:
|
||||
port: 80
|
||||
|
||||
postgres:
|
||||
image:
|
||||
repository: postgres
|
||||
tag: "14-alpine"
|
||||
storage:
|
||||
size: 5Gi
|
||||
className: "local-path" # Based on your cluster info
|
||||
auth:
|
||||
username: evrak_user
|
||||
database: evrak
|
||||
# Password should be managed via secrets, but for simplicity in values we can set a default or require it to be passed
|
||||
# In production, use --set postgres.auth.password=...
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
className: traefik
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod # Assuming you have this, or remove if not
|
||||
Reference in New Issue
Block a user