From 77c44c44ce4b0643d10864077ea35d93065f3d6c Mon Sep 17 00:00:00 2001 From: root Date: Thu, 30 Jul 2026 07:18:02 +0200 Subject: [PATCH] feat: Gitea Actions + k8s manifests + ArgoCD for k3s deploy --- .gitea/workflows/build.yaml | 43 ++++++++++++++++++++++++ k8s/app-config.yaml | 21 ++++++++++++ k8s/app.yaml | 56 +++++++++++++++++++++++++++++++ k8s/argocd-app.yaml | 27 +++++++++++++++ k8s/ingress.yaml | 24 +++++++++++++ k8s/kustomization.yaml | 15 +++++++++ k8s/namespace.yaml | 4 +++ k8s/postgres.yaml | 67 +++++++++++++++++++++++++++++++++++++ 8 files changed, 257 insertions(+) create mode 100644 .gitea/workflows/build.yaml create mode 100644 k8s/app-config.yaml create mode 100644 k8s/app.yaml create mode 100644 k8s/argocd-app.yaml create mode 100644 k8s/ingress.yaml create mode 100644 k8s/kustomization.yaml create mode 100644 k8s/namespace.yaml create mode 100644 k8s/postgres.yaml diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml new file mode 100644 index 0000000..cecf22a --- /dev/null +++ b/.gitea/workflows/build.yaml @@ -0,0 +1,43 @@ +name: Build & Push Docker Image +run-name: Build ${{ gitea.ref_name }} + +on: + push: + branches: [main] + tags: ["v*"] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Gitea Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ gitea.server_url }} + username: ${{ secrets.GITEA_USER }} + password: ${{ secrets.GITEA_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ gitea.server_url }}/${{ gitea.repository }} + tags: | + type=sha,format=long + type=ref,event=branch + type=semver,pattern={{version}} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/k8s/app-config.yaml b/k8s/app-config.yaml new file mode 100644 index 0000000..92814d7 --- /dev/null +++ b/k8s/app-config.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: app-config + namespace: toolrate +data: + PORT: "8080" + NODE_ENV: production + LOCAL_ADMIN_USERNAME: admin +--- +apiVersion: v1 +kind: Secret +metadata: + name: app-secrets + namespace: toolrate +type: Opaque +stringData: + POSTGRES_PASSWORD: changeme + SESSION_SECRET: change-this-to-a-random-64-char-string + LOCAL_ADMIN_PASSWORD: pssw0rd + DATABASE_URL: postgres://toolrate:changeme@postgres:5432/toolrate diff --git a/k8s/app.yaml b/k8s/app.yaml new file mode 100644 index 0000000..7a5c45f --- /dev/null +++ b/k8s/app.yaml @@ -0,0 +1,56 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: app + namespace: toolrate +spec: + replicas: 1 + selector: + matchLabels: + app: toolrate + template: + metadata: + labels: + app: toolrate + spec: + containers: + - name: app + image: gitea.example.com/your-org/tool-evaluator:sha-abcdef + ports: + - containerPort: 8080 + envFrom: + - configMapRef: + name: app-config + - secretRef: + name: app-secrets + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + livenessProbe: + httpGet: + path: /api/healthz + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 15 + readinessProbe: + httpGet: + path: /api/healthz + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: app + namespace: toolrate +spec: + selector: + app: toolrate + ports: + - port: 8080 + targetPort: 8080 diff --git a/k8s/argocd-app.yaml b/k8s/argocd-app.yaml new file mode 100644 index 0000000..ebe3a85 --- /dev/null +++ b/k8s/argocd-app.yaml @@ -0,0 +1,27 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: toolrate + namespace: argocd +spec: + project: default + source: + repoURL: https://gitea.example.com/your-org/tool-evaluator.git + targetRevision: main + path: k8s + destination: + server: https://kubernetes.default.svc + namespace: toolrate + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + - ApplyOutOfSyncOnly=true + ignoreDifferences: + - group: apps + kind: StatefulSet + jsonPointers: + - /spec/replicas + - /spec/template/spec/containers/0/image diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml new file mode 100644 index 0000000..513f38d --- /dev/null +++ b/k8s/ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: app + namespace: toolrate + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod +spec: + ingressClassName: traefik + rules: + - host: tools.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: app + port: + number: 8080 + tls: + - hosts: + - tools.example.com + secretName: app-tls diff --git a/k8s/kustomization.yaml b/k8s/kustomization.yaml new file mode 100644 index 0000000..f0f6c72 --- /dev/null +++ b/k8s/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: toolrate + +resources: + - namespace.yaml + - postgres.yaml + - app-config.yaml + - app.yaml + - ingress.yaml + +images: + - name: gitea.example.com/your-org/tool-evaluator + newName: gitea.example.com/your-org/tool-evaluator + newTag: sha-abcdef diff --git a/k8s/namespace.yaml b/k8s/namespace.yaml new file mode 100644 index 0000000..2453799 --- /dev/null +++ b/k8s/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: toolrate diff --git a/k8s/postgres.yaml b/k8s/postgres.yaml new file mode 100644 index 0000000..5ceccec --- /dev/null +++ b/k8s/postgres.yaml @@ -0,0 +1,67 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: postgres + namespace: toolrate +spec: + serviceName: postgres + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:16-alpine + ports: + - containerPort: 5432 + name: pg + env: + - name: POSTGRES_USER + value: toolrate + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: app-secrets + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: toolrate + volumeMounts: + - name: data + mountPath: /var/lib/postgresql/data + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + livenessProbe: + exec: + command: [pg_isready, -U, toolrate] + initialDelaySeconds: 15 + periodSeconds: 10 + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: [ReadWriteOnce] + resources: + requests: + storage: 10Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: toolrate +spec: + selector: + app: postgres + ports: + - port: 5432 + targetPort: 5432