diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 94349e8a..69a5031d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,18 +43,7 @@ deploy: script: - kubectl config get-contexts - kubectl config use-context graham/towerops:towerops - # Run database migrations before deploying new version - - | - # Create unique job name using commit SHA (truncated to fit k8s naming limits) - JOB_NAME="towerops-migrate-${CI_COMMIT_SHORT_SHA}" - # Generate job manifest with correct image tag and unique name - sed -e "s|IMAGE_TAG|${CI_COMMIT_SHA}|g" \ - -e "s|towerops-migrate-TIMESTAMP|${JOB_NAME}|g" \ - k8s/migrate-job.yaml | kubectl apply -f - - # Wait for migration to complete (max 5 minutes) - kubectl wait --for=condition=complete --timeout=5m job/${JOB_NAME} -n towerops - echo "Database migration completed successfully" - # Deploy new version + # Deploy new version (migrations run on app start) - kubectl set image deployment/towerops towerops=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -n towerops - kubectl rollout status deployment/towerops -n towerops --timeout=5m environment: diff --git a/k8s/migrate-job.yaml b/k8s/migrate-job.yaml deleted file mode 100644 index 3d085805..00000000 --- a/k8s/migrate-job.yaml +++ /dev/null @@ -1,59 +0,0 @@ ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: towerops-migrate-TIMESTAMP - namespace: towerops - labels: - app: towerops - component: migration -spec: - # Clean up completed jobs after 1 hour - ttlSecondsAfterFinished: 3600 - backoffLimit: 3 - template: - metadata: - labels: - app: towerops - component: migration - spec: - restartPolicy: Never - imagePullSecrets: - - name: gitlab-registry - securityContext: - runAsNonRoot: true - runAsUser: 65534 - fsGroup: 65534 - seccompProfile: - type: RuntimeDefault - containers: - - name: migrate - image: registry.gitlab.com/graham/towerops:IMAGE_TAG - command: ["/app/bin/towerops", "eval", "Towerops.Release.migrate()"] - securityContext: - allowPrivilegeEscalation: false - runAsNonRoot: true - runAsUser: 65534 - capabilities: - drop: - - ALL - seccompProfile: - type: RuntimeDefault - env: - - name: MIX_ENV - value: "prod" - - name: RELEASE_COOKIE - valueFrom: - secretKeyRef: - name: towerops-secrets - key: RELEASE_COOKIE - envFrom: - - secretRef: - name: towerops-db - resources: - requests: - memory: "128Mi" - cpu: "100m" - limits: - memory: "256Mi" - cpu: "500m" diff --git a/lib/towerops/application.ex b/lib/towerops/application.ex index 78d680d9..a7eca3c7 100644 --- a/lib/towerops/application.ex +++ b/lib/towerops/application.ex @@ -7,6 +7,11 @@ defmodule Towerops.Application do @impl true def start(_type, _args) do + # Run migrations on startup (Ecto handles locking for concurrent runs) + unless Application.get_env(:towerops, Towerops.Repo)[:database] == "towerops_test" do + Towerops.Release.migrate() + end + topologies = Application.get_env(:libcluster, :topologies, []) children = [