From 572e14d1ddb85367cd2c14e51c938a1aea3fbac8 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Tue, 17 Feb 2026 16:09:16 +0200 Subject: [PATCH 01/20] Create cicd pipline --- .gitlab-ci.yml | 106 +++++++++++++++++++++++++++++++++ README.md | 65 ++++++++++++++++++++ open-meteo-service/values.yaml | 16 ++--- 3 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..1bfee24 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,106 @@ +deploy_test: + stage: deploy_test + image: ubuntu:22.04 + before_script: + - | + set -euo pipefail + apt-get update && apt-get install -y curl ca-certificates jq + + echo "Installing kubectl ${KUBECTL_VERSION}..." + curl -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" + chmod +x kubectl && mv kubectl /usr/local/bin/ + kubectl version --client + + echo "Installing kind ${KIND_VERSION}..." + curl -Lo kind "https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-linux-amd64" + chmod +x kind && mv kind /usr/local/bin/ + kind version + + echo "Installing Helm ${HELM_VERSION}..." + curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash -s -- --version ${HELM_VERSION} + helm version + script: + - | + set -euo pipefail + + echo "Creating kind cluster..." + kind create cluster --name ci-cluster --wait 5m + kubectl get nodes + kubectl cluster-info + + echo "Creating imagePullSecret for GitLab Registry..." + kubectl create secret docker-registry gitlab-registry \ + --docker-server="${CI_REGISTRY}" \ + --docker-username="${CI_REGISTRY_USER}" \ + --docker-password="${CI_REGISTRY_PASSWORD}" \ + --namespace="${NAMESPACE}" \ + --dry-run=client -o yaml | kubectl apply -f - + + echo "Deploying Helm chart..." + helm upgrade --install ${HELM_RELEASE_NAME} ${HELM_CHART_PATH} \ + --namespace ${NAMESPACE} --create-namespace \ + --set image.repository="${CI_REGISTRY_IMAGE}" \ + --set image.tag="${CI_COMMIT_SHORT_SHA}" \ + --set image.pullPolicy=Always \ + --set imagePullSecrets[0].name=gitlab-registry \ + --set prometheus.enabled=false \ + --set grafana.enabled=false \ + --wait --timeout 5m + + echo "Cluster state after deploy:" + kubectl get pods -n ${NAMESPACE} + kubectl get svc -n ${NAMESPACE} + + echo "Waiting for API pod to become Ready..." + if ! kubectl wait --for=condition=ready pod \ + -l app.kubernetes.io/name=open-meteo-service \ + -n ${NAMESPACE} --timeout=180s; then + echo "ERROR: Pod not ready. Debug info:" + kubectl get pods -n ${NAMESPACE} + kubectl describe pods -l app.kubernetes.io/name=open-meteo-service -n ${NAMESPACE} + kubectl logs -l app.kubernetes.io/name=open-meteo-service -n ${NAMESPACE} --tail=200 + exit 1 + fi + + echo "Starting port-forward in background..." + kubectl port-forward -n ${NAMESPACE} svc/${SERVICE_NAME} 8000:8000 >/tmp/pf.log 2>&1 & + PF_PID=$! + sleep 5 + + echo "Testing /healthz..." + for i in $(seq 1 10); do + if curl -fsS --max-time 5 http://localhost:8000/healthz >/dev/null; then + echo "SUCCESS: /healthz endpoint is healthy" + break + fi + echo "Retry $i..." + sleep 3 + if [ "$i" -eq 10 ]; then + echo "ERROR: /healthz failed after 10 attempts" + echo "--- port-forward logs ---" + cat /tmp/pf.log || true + exit 1 + fi + done + + echo "Testing /coordinates..." + COORD_RESPONSE="$(curl -fsS --max-time 15 http://localhost:8000/coordinates)" + echo "$COORD_RESPONSE" | head -50 + if ! echo "$COORD_RESPONSE" | grep -q '"data"'; then + echo "ERROR: missing data field in response" + exit 1 + fi + echo "SUCCESS: /coordinates endpoint working" + + echo "Testing /metrics..." + curl -fsS --max-time 10 http://localhost:8000/metrics | head -30 + echo "SUCCESS: /metrics endpoint working" + + echo "SUCCESS: All tests passed" + kill $PF_PID || true + after_script: + - | + echo "Final cluster state:" + kubectl get all -n ${NAMESPACE} || true + echo "Deleting kind cluster..." + kind delete cluster --name ci-cluster || true diff --git a/README.md b/README.md index e852044..b8a38b6 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,71 @@ helm install open-meteo-service ./helm \ --set grafana.persistence.enabled=true ``` +## CI Pipeline + +This project includes a GitLab CI/CD pipeline that automatically builds, deploys, and tests the application without requiring Docker-in-Docker. + +### Pipeline Stages + +1. **Build Stage (Kaniko)** + - Builds Docker image using Kaniko (secure, daemonless container builder) + - Pushes to GitLab Container Registry with commit-based tags + - Tags `latest` for main branch builds + - Uses layer caching for faster builds + +2. **Deploy Stage (kind + Helm)** + - Creates a local Kubernetes cluster using kind (Kubernetes in Docker) + - Installs kubectl, kind, and Helm + - Configures image pull secrets for GitLab registry access + - Deploys app using Helm with the newly built image + - Waits for deployment readiness with automatic rollback on failure + +3. **Test Stage (Health Checks)** + - Validates deployment with port-forwarding + - Tests `/healthz` endpoint for service health + - Tests `/coordinates` endpoint for data retrieval + - Tests `/help` endpoint for API documentation + - Provides detailed debugging info if tests fail + - Cleans up kind cluster after tests + +### Image Tagging Strategy +- **Commit builds**: `$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA` +- **Main branch**: Also tagged as `latest` + +### Viewing Pipeline Status +1. Go to your GitLab project +2. Navigate to **CI/CD > Pipelines** +3. Click on a pipeline run to see individual job logs +4. Each stage shows real-time logs and can be expanded for details + +### Debugging Failed Pipelines +If a pipeline fails: +- Check the **build** job logs for Docker build errors +- Check the **deploy** job logs for Kubernetes/Helm issues + - Pod status and events are automatically logged + - Container logs are shown if deployment fails +- Check the **test** job logs for endpoint test failures + - Response bodies are printed for debugging + +### Running Locally +To test the pipeline behavior locally: +```bash +# Build with Kaniko (requires Docker) +docker run --rm -v $(pwd):/workspace gcr.io/kaniko-project/executor:latest \ + --dockerfile /workspace/Dockerfile \ + --context /workspace \ + --no-push + +# Test with kind +kind create cluster +kubectl create secret docker-registry gitlab-registry \ + --docker-server=your-registry \ + --docker-username=your-user \ + --docker-password=your-token +helm install open-meteo-service ./open-meteo-service \ + --set imagePullSecrets[0].name=gitlab-registry +``` + ## API Documentation ### Endpoints diff --git a/open-meteo-service/values.yaml b/open-meteo-service/values.yaml index 27de93a..c68f521 100644 --- a/open-meteo-service/values.yaml +++ b/open-meteo-service/values.yaml @@ -1,8 +1,8 @@ replicaCount: 1 image: - repository: harbor.dvirlabs.com/my-apps/open-meteo-service - tag: "1.0.2" + repository: harbor.dvirlabs.com/library/open-meteo-service + tag: "1.0.3" pullPolicy: IfNotPresent imagePullSecrets: @@ -13,7 +13,7 @@ service: port: 8000 ingress: - enabled: true + enabled: false className: "traefik" hosts: - host: open-meteo.dvirlabs.com @@ -35,7 +35,7 @@ persistence: accessModes: - ReadWriteOnce size: 1Gi - storageClassName: "" + storageClassName: "standard" resources: {} @@ -53,7 +53,7 @@ prometheus: type: ClusterIP port: 9090 ingress: - enabled: true + enabled: false className: "traefik" hosts: - host: open-meteo-prometheus.dvirlabs.com @@ -66,7 +66,7 @@ prometheus: accessModes: - ReadWriteOnce size: 5Gi - storageClassName: "" + storageClassName: "standard" resources: {} extraArgs: [] @@ -80,7 +80,7 @@ grafana: adminUser: admin adminPassword: admin ingress: - enabled: true + enabled: false className: "traefik" hosts: - host: open-meteo-grafana.dvirlabs.com @@ -93,5 +93,5 @@ grafana: accessModes: - ReadWriteOnce size: 5Gi - storageClassName: "" + storageClassName: "standard" resources: {} \ No newline at end of file From 76d3359896ab84014c82cfc79a799cdd0bdbd6a6 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 04:04:35 +0200 Subject: [PATCH 02/20] Update the pipeline to deploy on my k3s cluster andupdate the values --- .gitlab-ci.yml | 166 +++++++++++++++------------------ README.md | 109 ++++++++++++---------- open-meteo-service/values.yaml | 26 +++--- values.yaml | 97 +++++++++++++++++++ 4 files changed, 242 insertions(+), 156 deletions(-) create mode 100644 values.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1bfee24..ba8cf24 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,106 +1,88 @@ -deploy_test: - stage: deploy_test - image: ubuntu:22.04 - before_script: - - | - set -euo pipefail - apt-get update && apt-get install -y curl ca-certificates jq +stages: [build, deploy] - echo "Installing kubectl ${KUBECTL_VERSION}..." - curl -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" - chmod +x kubectl && mv kubectl /usr/local/bin/ - kubectl version --client +variables: + IMAGE_REPO: "$CI_REGISTRY_IMAGE" + TAG: "${CI_COMMIT_REF_SLUG}-${CI_COMMIT_SHORT_SHA}" + RELEASE: "open-meteo-service-gitlab" + NAMESPACE: "sandbox-gitlab" + CHART_PATH: "./open-meteo-service" + VALUES_FILE: "./open-meteo-service/values.yaml" + SERVICE_NAME: "open-meteo-service-open-meteo-service" # <-- אם אצלך שם אחר, תשנה פה - echo "Installing kind ${KIND_VERSION}..." - curl -Lo kind "https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-linux-amd64" - chmod +x kind && mv kind /usr/local/bin/ - kind version - - echo "Installing Helm ${HELM_VERSION}..." - curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash -s -- --version ${HELM_VERSION} - helm version +build: + stage: build + tags: [homelab] script: - - | - set -euo pipefail + - docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" + - docker build -t "$IMAGE_REPO:$TAG" . + - docker push "$IMAGE_REPO:$TAG" + - docker tag "$IMAGE_REPO:$TAG" "$IMAGE_REPO:latest" + - docker push "$IMAGE_REPO:latest" + - echo "Built and pushed $IMAGE_REPO:$TAG and $IMAGE_REPO:latest" - echo "Creating kind cluster..." - kind create cluster --name ci-cluster --wait 5m - kubectl get nodes - kubectl cluster-info +deploy: + stage: deploy + tags: [homelab] + rules: + - if: '$CI_COMMIT_MESSAGE =~ /^ci: bump image tag/' + when: never + - when: on_success + script: |- + set -euo pipefail - echo "Creating imagePullSecret for GitLab Registry..." - kubectl create secret docker-registry gitlab-registry \ - --docker-server="${CI_REGISTRY}" \ - --docker-username="${CI_REGISTRY_USER}" \ - --docker-password="${CI_REGISTRY_PASSWORD}" \ - --namespace="${NAMESPACE}" \ - --dry-run=client -o yaml | kubectl apply -f - + # Install yq if missing + if ! command -v yq >/dev/null 2>&1; then + YQ_VERSION="v4.35.1" + wget -qO /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_amd64" + chmod +x /usr/local/bin/yq + fi - echo "Deploying Helm chart..." - helm upgrade --install ${HELM_RELEASE_NAME} ${HELM_CHART_PATH} \ - --namespace ${NAMESPACE} --create-namespace \ - --set image.repository="${CI_REGISTRY_IMAGE}" \ - --set image.tag="${CI_COMMIT_SHORT_SHA}" \ - --set image.pullPolicy=Always \ - --set imagePullSecrets[0].name=gitlab-registry \ - --set prometheus.enabled=false \ - --set grafana.enabled=false \ - --wait --timeout 5m + # Update values.yaml with the new tag + yq e ".image.tag = \"${TAG}\"" -i "${VALUES_FILE}" + echo "Updated ${VALUES_FILE} with image.tag=${TAG}" - echo "Cluster state after deploy:" - kubectl get pods -n ${NAMESPACE} - kubectl get svc -n ${NAMESPACE} + # Configure git identity + git config user.email "gitlab-ci@dvirlabs.com" + git config user.name "GitLab CI" - echo "Waiting for API pod to become Ready..." - if ! kubectl wait --for=condition=ready pod \ - -l app.kubernetes.io/name=open-meteo-service \ - -n ${NAMESPACE} --timeout=180s; then - echo "ERROR: Pod not ready. Debug info:" - kubectl get pods -n ${NAMESPACE} - kubectl describe pods -l app.kubernetes.io/name=open-meteo-service -n ${NAMESPACE} - kubectl logs -l app.kubernetes.io/name=open-meteo-service -n ${NAMESPACE} --tail=200 - exit 1 - fi + # Commit & push values bump (skip-ci to avoid loop) + git add "${VALUES_FILE}" + git commit -m "ci: bump image tag to ${TAG} [skip ci]" || echo "No changes to commit" - echo "Starting port-forward in background..." - kubectl port-forward -n ${NAMESPACE} svc/${SERVICE_NAME} 8000:8000 >/tmp/pf.log 2>&1 & - PF_PID=$! - sleep 5 + git remote set-url origin "https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" + git push origin "HEAD:${CI_COMMIT_REF_NAME}" || echo "Nothing to push" - echo "Testing /healthz..." - for i in $(seq 1 10); do - if curl -fsS --max-time 5 http://localhost:8000/healthz >/dev/null; then - echo "SUCCESS: /healthz endpoint is healthy" - break - fi - echo "Retry $i..." - sleep 3 - if [ "$i" -eq 10 ]; then - echo "ERROR: /healthz failed after 10 attempts" - echo "--- port-forward logs ---" - cat /tmp/pf.log || true - exit 1 - fi - done + echo "Deploying with Helm..." + helm upgrade --install "${RELEASE}" "${CHART_PATH}" \ + -n "${NAMESPACE}" \ + --create-namespace \ + --wait --timeout 5m - echo "Testing /coordinates..." - COORD_RESPONSE="$(curl -fsS --max-time 15 http://localhost:8000/coordinates)" - echo "$COORD_RESPONSE" | head -50 - if ! echo "$COORD_RESPONSE" | grep -q '"data"'; then - echo "ERROR: missing data field in response" - exit 1 - fi - echo "SUCCESS: /coordinates endpoint working" + echo "Waiting for deployment to be ready..." + kubectl -n "${NAMESPACE}" rollout status deploy -l app.kubernetes.io/name=open-meteo-service --timeout=180s - echo "Testing /metrics..." - curl -fsS --max-time 10 http://localhost:8000/metrics | head -30 - echo "SUCCESS: /metrics endpoint working" + echo "Port-forward for tests..." + kubectl -n "${NAMESPACE}" port-forward "svc/${SERVICE_NAME}" 8000:8000 >/tmp/pf.log 2>&1 & + PF_PID=$! + sleep 5 - echo "SUCCESS: All tests passed" + echo "Testing /healthz..." + curl -fsS http://localhost:8000/healthz >/dev/null + echo "OK /healthz" + + echo "Testing /coordinates..." + COORDS_RESPONSE="$(curl -fsS http://localhost:8000/coordinates)" + echo "$COORDS_RESPONSE" | head -20 + if ! echo "$COORDS_RESPONSE" | grep -q '"data"'; then + echo "ERROR: /coordinates response missing 'data' field" kill $PF_PID || true - after_script: - - | - echo "Final cluster state:" - kubectl get all -n ${NAMESPACE} || true - echo "Deleting kind cluster..." - kind delete cluster --name ci-cluster || true + exit 1 + fi + echo "OK /coordinates" + + echo "Testing /metrics..." + curl -fsS http://localhost:8000/metrics | head -20 + echo "OK /metrics" + + kill $PF_PID || true + echo "All tests passed!" diff --git a/README.md b/README.md index b8a38b6..cbc0ca0 100644 --- a/README.md +++ b/README.md @@ -99,69 +99,76 @@ helm install open-meteo-service ./helm \ --set grafana.persistence.enabled=true ``` -## CI Pipeline +## GitLab CI Workflow -This project includes a GitLab CI/CD pipeline that automatically builds, deploys, and tests the application without requiring Docker-in-Docker. +This project uses a GitLab CI/CD pipeline that automates building, versioning, deployment, and testing on an external k3s cluster (homelab). -### Pipeline Stages +### Pipeline Overview -1. **Build Stage (Kaniko)** - - Builds Docker image using Kaniko (secure, daemonless container builder) - - Pushes to GitLab Container Registry with commit-based tags - - Tags `latest` for main branch builds - - Uses layer caching for faster builds +The pipeline consists of two stages: **build** and **deploy**. -2. **Deploy Stage (kind + Helm)** - - Creates a local Kubernetes cluster using kind (Kubernetes in Docker) - - Installs kubectl, kind, and Helm - - Configures image pull secrets for GitLab registry access - - Deploys app using Helm with the newly built image - - Waits for deployment readiness with automatic rollback on failure +#### 1. Build Stage +- **Docker Image Build**: Builds the application Docker image using the project Dockerfile +- **Tagging Strategy**: Tags each image with a unique identifier combining branch and commit SHA: + - Format: `-` (e.g., `main-a1b2c3d`, `feature-api-xyz1234`) + - Uses `CI_COMMIT_REF_SLUG` (sanitized branch name) and `CI_COMMIT_SHORT_SHA` +- **Multi-Tag Push**: Pushes two tags to GitLab Container Registry: + - `$IMAGE_REPO:-` - Specific version tag + - `$IMAGE_REPO:latest` - Always points to the most recent build +- **Registry Authentication**: Uses GitLab's built-in CI variables (`CI_REGISTRY`, `CI_REGISTRY_USER`, `CI_REGISTRY_PASSWORD`) -3. **Test Stage (Health Checks)** - - Validates deployment with port-forwarding - - Tests `/healthz` endpoint for service health - - Tests `/coordinates` endpoint for data retrieval - - Tests `/help` endpoint for API documentation - - Provides detailed debugging info if tests fail - - Cleans up kind cluster after tests +#### 2. Deploy Stage +- **Values File Update**: + - Uses `yq` to update `open-meteo-service/values.yaml` + - Sets `image.tag` to the newly built tag (`-`) + - Keeps `image.repository` constant in the values file + - Commits the change with message: `ci: bump image tag to [skip ci]` + - Pushes back to the repository using `CI_JOB_TOKEN` for authentication +- **Helm Deployment**: + - Deploys to namespace: `sandbox-gitlab` + - Release name: `open-meteo-service-gitlab` + - Uses the updated values.yaml file from the workspace + - Waits for deployment to be ready (5-minute timeout) +- **Automated Tests**: + - Port-forwards the service to localhost:8000 + - `/healthz` - Checks service health + - `/coordinates` - Validates JSON response contains `"data"` field + - `/metrics` - Ensures metrics endpoint is accessible + - All tests must pass for the pipeline to succeed -### Image Tagging Strategy -- **Commit builds**: `$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA` -- **Main branch**: Also tagged as `latest` +### Preventing Infinite Loops + +The pipeline includes safeguards to prevent infinite pipeline triggers: +- The deploy job includes a rule: `if: '$CI_COMMIT_MESSAGE =~ /^ci: bump image tag/'` with `when: never` +- The values bump commit includes `[skip ci]` to prevent triggering a new pipeline +- The deploy job uses the already-updated values.yaml in the current workspace + +### Deployment Target + +- **Cluster**: External k3s homelab cluster (not ephemeral) +- **Runner**: Self-hosted GitLab runner tagged with `homelab` +- **Namespace**: `sandbox-gitlab` (separate from ArgoCD/Harbor setups) +- **Ingress**: Configured for `open-meteo-gitlab.dvirlabs.com` (see values.yaml) ### Viewing Pipeline Status -1. Go to your GitLab project -2. Navigate to **CI/CD > Pipelines** -3. Click on a pipeline run to see individual job logs -4. Each stage shows real-time logs and can be expanded for details -### Debugging Failed Pipelines -If a pipeline fails: -- Check the **build** job logs for Docker build errors -- Check the **deploy** job logs for Kubernetes/Helm issues - - Pod status and events are automatically logged - - Container logs are shown if deployment fails -- Check the **test** job logs for endpoint test failures - - Response bodies are printed for debugging +1. Navigate to **CI/CD > Pipelines** in your GitLab project +2. Click on any pipeline run to see job details +3. Expand jobs to view real-time logs +4. The deploy job shows Helm output, rollout status, and test results -### Running Locally -To test the pipeline behavior locally: +### Manual Deployment + +To deploy manually with a specific tag: ```bash -# Build with Kaniko (requires Docker) -docker run --rm -v $(pwd):/workspace gcr.io/kaniko-project/executor:latest \ - --dockerfile /workspace/Dockerfile \ - --context /workspace \ - --no-push +# Option 1: Deploy using updated values.yaml +helm upgrade --install open-meteo-service-gitlab ./open-meteo-service \ + -n sandbox-gitlab --create-namespace -# Test with kind -kind create cluster -kubectl create secret docker-registry gitlab-registry \ - --docker-server=your-registry \ - --docker-username=your-user \ - --docker-password=your-token -helm install open-meteo-service ./open-meteo-service \ - --set imagePullSecrets[0].name=gitlab-registry +# Option 2: Override tag via --set +helm upgrade --install open-meteo-service-gitlab ./open-meteo-service \ + -n sandbox-gitlab --create-namespace \ + --set image.tag=main-a1b2c3d ``` ## API Documentation diff --git a/open-meteo-service/values.yaml b/open-meteo-service/values.yaml index c68f521..47626fa 100644 --- a/open-meteo-service/values.yaml +++ b/open-meteo-service/values.yaml @@ -1,12 +1,12 @@ replicaCount: 1 image: - repository: harbor.dvirlabs.com/library/open-meteo-service - tag: "1.0.3" + repository: registry.gitlab.com/dvirlabs/open-meteo-service + tag: "latest" pullPolicy: IfNotPresent imagePullSecrets: - - name: harbor-regcred + - name: gitlab-registry service: type: ClusterIP @@ -14,9 +14,9 @@ service: ingress: enabled: false - className: "traefik" + className: "" hosts: - - host: open-meteo.dvirlabs.com + - host: open-meteo-gitlab.dvirlabs.com paths: - path: / pathType: Prefix @@ -35,7 +35,7 @@ persistence: accessModes: - ReadWriteOnce size: 1Gi - storageClassName: "standard" + storageClassName: "" resources: {} @@ -54,9 +54,9 @@ prometheus: port: 9090 ingress: enabled: false - className: "traefik" + className: "" hosts: - - host: open-meteo-prometheus.dvirlabs.com + - host: prometheus.local paths: - path: / pathType: Prefix @@ -66,7 +66,7 @@ prometheus: accessModes: - ReadWriteOnce size: 5Gi - storageClassName: "standard" + storageClassName: "" resources: {} extraArgs: [] @@ -81,9 +81,9 @@ grafana: adminPassword: admin ingress: enabled: false - className: "traefik" + className: "" hosts: - - host: open-meteo-grafana.dvirlabs.com + - host: grafana.local paths: - path: / pathType: Prefix @@ -93,5 +93,5 @@ grafana: accessModes: - ReadWriteOnce size: 5Gi - storageClassName: "standard" - resources: {} \ No newline at end of file + storageClassName: "" + resources: {} diff --git a/values.yaml b/values.yaml new file mode 100644 index 0000000..174b350 --- /dev/null +++ b/values.yaml @@ -0,0 +1,97 @@ +replicaCount: 1 + +image: + repository: registry.gitlab.com/dvirlabs/open-meteo-service + tag: "latest" + pullPolicy: IfNotPresent + +imagePullSecrets: +- name: gitlab-registry + +service: + type: ClusterIP + port: 8000 + +ingress: + enabled: true + className: "traefik" + hosts: + - host: open-meteo-gitlab.dvirlabs.com + paths: + - path: / + pathType: Prefix + tls: [] + +podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/path: /metrics + prometheus.io/port: "8000" + +env: + cacheFile: /data/coordinates_cache.json + +persistence: + enabled: false + accessModes: + - ReadWriteOnce + size: 1Gi + storageClassName: "nfs-client" + +resources: {} + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +prometheus: + enabled: true + replicaCount: 1 + image: prom/prometheus:latest + service: + type: ClusterIP + port: 9090 + ingress: + enabled: true + className: "traefik" + hosts: + - host: open-meteo-prometheus-gitlab.dvirlabs.com + paths: + - path: / + pathType: Prefix + tls: [] + persistence: + enabled: true + accessModes: + - ReadWriteOnce + size: 5Gi + storageClassName: "nfs-client" + resources: {} + extraArgs: [] + +grafana: + enabled: true + replicaCount: 1 + image: grafana/grafana:latest + service: + type: ClusterIP + port: 3000 + adminUser: admin + adminPassword: admin + ingress: + enabled: true + className: "traefik" + hosts: + - host: open-meteo-grafana-gitlab.dvirlabs.com + paths: + - path: / + pathType: Prefix + tls: [] + persistence: + enabled: true + accessModes: + - ReadWriteOnce + size: 5Gi + storageClassName: "nfs-client" + resources: {} From 31bce27adfcb538a09a7f420ac82d51cac0c94a6 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 04:22:47 +0200 Subject: [PATCH 03/20] Update the registry --- values.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/values.yaml b/values.yaml index 174b350..49b4b53 100644 --- a/values.yaml +++ b/values.yaml @@ -1,7 +1,7 @@ replicaCount: 1 image: - repository: registry.gitlab.com/dvirlabs/open-meteo-service + repository: registry.gitlab.com/dvirlabs-group/open-meteo-service tag: "latest" pullPolicy: IfNotPresent @@ -13,7 +13,7 @@ service: port: 8000 ingress: - enabled: true + enabled: false className: "traefik" hosts: - host: open-meteo-gitlab.dvirlabs.com @@ -53,7 +53,7 @@ prometheus: type: ClusterIP port: 9090 ingress: - enabled: true + enabled: false className: "traefik" hosts: - host: open-meteo-prometheus-gitlab.dvirlabs.com @@ -80,7 +80,7 @@ grafana: adminUser: admin adminPassword: admin ingress: - enabled: true + enabled: false className: "traefik" hosts: - host: open-meteo-grafana-gitlab.dvirlabs.com From f0d8a1d4dada19661d9308e5ceb39b34a6498a24 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 10:16:45 +0200 Subject: [PATCH 04/20] Update the registry --- values.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/values.yaml b/values.yaml index 49b4b53..cf14112 100644 --- a/values.yaml +++ b/values.yaml @@ -95,3 +95,4 @@ grafana: size: 5Gi storageClassName: "nfs-client" resources: {} + From f490012ceccf4130cc0cf801da46e89c6853bddb Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 10:24:00 +0200 Subject: [PATCH 05/20] Update yq command --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ba8cf24..2c183a9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,8 +33,8 @@ deploy: # Install yq if missing if ! command -v yq >/dev/null 2>&1; then YQ_VERSION="v4.35.1" - wget -qO /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_amd64" - chmod +x /usr/local/bin/yq + wget -qO /usr/bin/yq "https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_amd64" + chmod +x /usr/bin/yq fi # Update values.yaml with the new tag From c155dc6b4da2243e99b85bf7b807e8d0e9587de0 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 10:29:57 +0200 Subject: [PATCH 06/20] Update yq bin path --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2c183a9..e2fed4e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -38,7 +38,7 @@ deploy: fi # Update values.yaml with the new tag - yq e ".image.tag = \"${TAG}\"" -i "${VALUES_FILE}" + /tmp/yq e ".image.tag = \"${TAG}\"" -i "${VALUES_FILE}" echo "Updated ${VALUES_FILE} with image.tag=${TAG}" # Configure git identity From 51a6b38c6c6d09d272c7cc0381fe665359175858 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 10:34:57 +0200 Subject: [PATCH 07/20] Test push --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e2fed4e..0c64775 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -85,4 +85,4 @@ deploy: echo "OK /metrics" kill $PF_PID || true - echo "All tests passed!" + echo "All tests passed!" \ No newline at end of file From 0d356fb85dff053f032bc5eefb4d658a28ad4172 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 10:38:13 +0200 Subject: [PATCH 08/20] Test push --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0c64775..af6157c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -85,4 +85,5 @@ deploy: echo "OK /metrics" kill $PF_PID || true - echo "All tests passed!" \ No newline at end of file + echo "All tests passed!" + \ No newline at end of file From 5a6d11c650319369d10ab3316a6794416dbae46a Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 10:48:24 +0200 Subject: [PATCH 09/20] Set the env --- .gitlab-ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index af6157c..6c72623 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,6 +13,10 @@ build: stage: build tags: [homelab] script: + - whoami + - set -euo pipefail + - unset DOCKER_HOST DOCKER_TLS_VERIFY DOCKER_CERT_PATH || true + - export DOCKER_HOST=unix:///var/run/docker.sock - docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" - docker build -t "$IMAGE_REPO:$TAG" . - docker push "$IMAGE_REPO:$TAG" @@ -86,4 +90,3 @@ deploy: kill $PF_PID || true echo "All tests passed!" - \ No newline at end of file From 7e6521f3bfa9d4985dd516a8ae1cac797c1c2555 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 10:51:45 +0200 Subject: [PATCH 10/20] Set the VALUES_FILE env --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6c72623..1966dfe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,7 +6,7 @@ variables: RELEASE: "open-meteo-service-gitlab" NAMESPACE: "sandbox-gitlab" CHART_PATH: "./open-meteo-service" - VALUES_FILE: "./open-meteo-service/values.yaml" + VALUES_FILE: "./values.yaml" SERVICE_NAME: "open-meteo-service-open-meteo-service" # <-- אם אצלך שם אחר, תשנה פה build: From 35a5afc715327ea105c1bbce50e57952e427e10f Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 10:54:16 +0200 Subject: [PATCH 11/20] Test push --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1966dfe..46e3ed2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -89,4 +89,4 @@ deploy: echo "OK /metrics" kill $PF_PID || true - echo "All tests passed!" + echo "All tests passed!" \ No newline at end of file From cbefc542279fe2bdf27a2705956c30910d80ad33 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 10:58:10 +0200 Subject: [PATCH 12/20] Test push --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 46e3ed2..5c01660 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -89,4 +89,5 @@ deploy: echo "OK /metrics" kill $PF_PID || true - echo "All tests passed!" \ No newline at end of file + echo "All tests passed!" + \ No newline at end of file From fd817b5334b06b2c3ea7cdbc8cc3014636f60f65 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 11:01:52 +0200 Subject: [PATCH 13/20] Set the VALUES_FILE env --- .gitlab-ci.yml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5c01660..824910b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,6 @@ variables: NAMESPACE: "sandbox-gitlab" CHART_PATH: "./open-meteo-service" VALUES_FILE: "./values.yaml" - SERVICE_NAME: "open-meteo-service-open-meteo-service" # <-- אם אצלך שם אחר, תשנה פה build: stage: build @@ -34,16 +33,12 @@ deploy: script: |- set -euo pipefail - # Install yq if missing - if ! command -v yq >/dev/null 2>&1; then - YQ_VERSION="v4.35.1" - wget -qO /usr/bin/yq "https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_amd64" - chmod +x /usr/bin/yq - fi - - # Update values.yaml with the new tag - /tmp/yq e ".image.tag = \"${TAG}\"" -i "${VALUES_FILE}" + # Update values.yaml with the new tag using sed + sed -i "s/^ tag: .*/ tag: \"${TAG}\"/" "${VALUES_FILE}" echo "Updated ${VALUES_FILE} with image.tag=${TAG}" + + # Verify the change + grep -A 1 "^image:" "${VALUES_FILE}" # Configure git identity git config user.email "gitlab-ci@dvirlabs.com" @@ -58,6 +53,7 @@ deploy: echo "Deploying with Helm..." helm upgrade --install "${RELEASE}" "${CHART_PATH}" \ + -f "${VALUES_FILE}" \ -n "${NAMESPACE}" \ --create-namespace \ --wait --timeout 5m @@ -66,6 +62,7 @@ deploy: kubectl -n "${NAMESPACE}" rollout status deploy -l app.kubernetes.io/name=open-meteo-service --timeout=180s echo "Port-forward for tests..." + SERVICE_NAME="${RELEASE}-open-meteo-service" kubectl -n "${NAMESPACE}" port-forward "svc/${SERVICE_NAME}" 8000:8000 >/tmp/pf.log 2>&1 & PF_PID=$! sleep 5 @@ -90,4 +87,3 @@ deploy: kill $PF_PID || true echo "All tests passed!" - \ No newline at end of file From f367a0d0325d2ea91befa4b06fce765e1da67618 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 11:05:59 +0200 Subject: [PATCH 14/20] Update gitlab token --- .gitlab-ci.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 824910b..5fe0a86 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,6 +33,11 @@ deploy: script: |- set -euo pipefail + # Configure kubectl for k3s cluster + export KUBECONFIG=/etc/rancher/k3s/k3s.yaml + echo "Configured kubectl to use k3s cluster" + kubectl cluster-info || echo "Warning: Could not connect to cluster yet" + # Update values.yaml with the new tag using sed sed -i "s/^ tag: .*/ tag: \"${TAG}\"/" "${VALUES_FILE}" echo "Updated ${VALUES_FILE} with image.tag=${TAG}" @@ -48,8 +53,13 @@ deploy: git add "${VALUES_FILE}" git commit -m "ci: bump image tag to ${TAG} [skip ci]" || echo "No changes to commit" - git remote set-url origin "https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" - git push origin "HEAD:${CI_COMMIT_REF_NAME}" || echo "Nothing to push" + # Push using GITLAB_TOKEN (set as CI/CD variable) + if [ -n "${GITLAB_TOKEN:-}" ]; then + git remote set-url origin "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST#https://}/${CI_PROJECT_PATH}.git" + git push origin "HEAD:${CI_COMMIT_REF_NAME}" && echo "Pushed values.yaml update" || echo "Failed to push, continuing anyway" + else + echo "GITLAB_TOKEN not set, skipping git push (values.yaml updated in workspace)" + fi echo "Deploying with Helm..." helm upgrade --install "${RELEASE}" "${CHART_PATH}" \ From 9435e9a915321c3e4ed7a81fe4e684a672f1a7cc Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 11:08:38 +0200 Subject: [PATCH 15/20] Test push --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5fe0a86..cf1f5ab 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -96,4 +96,4 @@ deploy: echo "OK /metrics" kill $PF_PID || true - echo "All tests passed!" + echo "All tests passed!" \ No newline at end of file From 5dab10b84336326a8d3ccf8e0c97c28e9ceaafc6 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 11:10:07 +0200 Subject: [PATCH 16/20] Update the k3s yaml --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cf1f5ab..14816b7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,7 +34,7 @@ deploy: set -euo pipefail # Configure kubectl for k3s cluster - export KUBECONFIG=/etc/rancher/k3s/k3s.yaml + export KUBECONFIG=/tmp/k3s.yaml echo "Configured kubectl to use k3s cluster" kubectl cluster-info || echo "Warning: Could not connect to cluster yet" From b1d56d1cb70d964f0323f9b18f40d066824bf5b7 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 11:17:33 +0200 Subject: [PATCH 17/20] Update the token --- .gitlab-ci.yml | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 14816b7..fd89094 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,7 +34,7 @@ deploy: set -euo pipefail # Configure kubectl for k3s cluster - export KUBECONFIG=/tmp/k3s.yaml + export KUBECONFIG=/etc/rancher/k3s/k3s.yaml echo "Configured kubectl to use k3s cluster" kubectl cluster-info || echo "Warning: Could not connect to cluster yet" @@ -43,7 +43,7 @@ deploy: echo "Updated ${VALUES_FILE} with image.tag=${TAG}" # Verify the change - grep -A 1 "^image:" "${VALUES_FILE}" + grep -A 2 "^image:" "${VALUES_FILE}" # Configure git identity git config user.email "gitlab-ci@dvirlabs.com" @@ -53,20 +53,33 @@ deploy: git add "${VALUES_FILE}" git commit -m "ci: bump image tag to ${TAG} [skip ci]" || echo "No changes to commit" - # Push using GITLAB_TOKEN (set as CI/CD variable) + # Push using GITLAB_TOKEN (Project Access Token with api scope) if [ -n "${GITLAB_TOKEN:-}" ]; then - git remote set-url origin "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST#https://}/${CI_PROJECT_PATH}.git" - git push origin "HEAD:${CI_COMMIT_REF_NAME}" && echo "Pushed values.yaml update" || echo "Failed to push, continuing anyway" + git remote set-url origin "https://oauth2:${GITLAB_TOKEN}@gitlab.com/${CI_PROJECT_PATH}.git" + git push origin "HEAD:${CI_COMMIT_REF_NAME}" && echo "Pushed values.yaml update successfully" || echo "Failed to push, continuing deployment anyway" else - echo "GITLAB_TOKEN not set, skipping git push (values.yaml updated in workspace)" + echo "GITLAB_TOKEN not set, skipping git push (values.yaml is updated locally for this deployment)" fi + # Create namespace if it doesn't exist + kubectl create namespace "${NAMESPACE}" --dry-run=client -o yaml | kubectl apply -f - + + # Create or update GitLab registry secret for pulling images + echo "Creating/updating image pull secret..." + kubectl create secret docker-registry gitlab-registry \ + --docker-server="${CI_REGISTRY}" \ + --docker-username="${CI_REGISTRY_USER}" \ + --docker-password="${CI_REGISTRY_PASSWORD}" \ + --namespace="${NAMESPACE}" \ + --dry-run=client -o yaml | kubectl apply -f - + echo "Deploying with Helm..." helm upgrade --install "${RELEASE}" "${CHART_PATH}" \ -f "${VALUES_FILE}" \ -n "${NAMESPACE}" \ --create-namespace \ - --wait --timeout 5m + --wait --timeout 10m \ + --debug echo "Waiting for deployment to be ready..." kubectl -n "${NAMESPACE}" rollout status deploy -l app.kubernetes.io/name=open-meteo-service --timeout=180s From 22c0f9b2ab8c6ed3df57404ed208b09831ca33f8 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 11:18:48 +0200 Subject: [PATCH 18/20] Update the k3s yaml --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fd89094..9d47bcc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,7 +34,7 @@ deploy: set -euo pipefail # Configure kubectl for k3s cluster - export KUBECONFIG=/etc/rancher/k3s/k3s.yaml + export KUBECONFIG=/tmp/k3s.yaml echo "Configured kubectl to use k3s cluster" kubectl cluster-info || echo "Warning: Could not connect to cluster yet" From 110ba605133e89592c2280c3c76cce07f10a9fc8 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 18 Feb 2026 11:33:59 +0200 Subject: [PATCH 19/20] Update the git url --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9d47bcc..9be2227 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,7 +55,7 @@ deploy: # Push using GITLAB_TOKEN (Project Access Token with api scope) if [ -n "${GITLAB_TOKEN:-}" ]; then - git remote set-url origin "https://oauth2:${GITLAB_TOKEN}@gitlab.com/${CI_PROJECT_PATH}.git" + git remote set-url origin "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" git push origin "HEAD:${CI_COMMIT_REF_NAME}" && echo "Pushed values.yaml update successfully" || echo "Failed to push, continuing deployment anyway" else echo "GITLAB_TOKEN not set, skipping git push (values.yaml is updated locally for this deployment)" From c8402fd5d8309dc9d24ce627f76d326ea95c2bf9 Mon Sep 17 00:00:00 2001 From: GitLab CI Date: Wed, 18 Feb 2026 09:34:36 +0000 Subject: [PATCH 20/20] ci: bump image tag to step3-110ba605 [skip ci] --- values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/values.yaml b/values.yaml index cf14112..d259377 100644 --- a/values.yaml +++ b/values.yaml @@ -2,7 +2,7 @@ replicaCount: 1 image: repository: registry.gitlab.com/dvirlabs-group/open-meteo-service - tag: "latest" + tag: "step3-110ba605" pullPolicy: IfNotPresent imagePullSecrets: