diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 65df90e6..637677a4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ variables: IMAGE_NAME: "${CI_REGISTRY_IMAGE}:${IMAGE_TAG}" IMAGE_LATEST: "${CI_REGISTRY_IMAGE}:staging_latest" - DEPLOY_DIR: "/opt/deploy/stg-lti-api" + DEPLOY_DIR: "/opt/deploy/stg-lti-api" COMPOSE_FILE: "docker-compose.yaml" # ========================= @@ -31,20 +31,22 @@ build_staging: stage: build rules: - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "staging"' - script: - - set -e - - docker info - - echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY" + script: | + set -e + docker info - - echo "✅ Build image: $IMAGE_NAME" - - docker build -t "$IMAGE_NAME" -f Dockerfile . + echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY" - - echo "✅ Push image: $IMAGE_NAME" - - docker push "$IMAGE_NAME" + echo "✅ Build image: $IMAGE_NAME" + docker build -t "$IMAGE_NAME" -f Dockerfile . + + echo "✅ Push image: $IMAGE_NAME" + docker push "$IMAGE_NAME" + + echo "✅ Tag latest: $IMAGE_LATEST" + docker tag "$IMAGE_NAME" "$IMAGE_LATEST" + docker push "$IMAGE_LATEST" - - echo "✅ Tag latest: $IMAGE_LATEST" - - docker tag "$IMAGE_NAME" "$IMAGE_LATEST" - - docker push "$IMAGE_LATEST" # ========================= # MIGRATE (AUTO) - JOIN COMPOSE NETWORK @@ -56,76 +58,72 @@ migrate_staging: needs: - job: build_staging artifacts: false - script: - - set -e - - echo "✅ Running migrations (staging) ..." + script: | + set -e + echo "✅ Running migrations (staging) ..." - # ✅ masuk deploy dir (ada .env + docker-compose) - - cd "$DEPLOY_DIR" - - test -f "$COMPOSE_FILE" || (echo "❌ $COMPOSE_FILE not found in $DEPLOY_DIR" && exit 1) - - test -f .env || (echo "❌ .env not found in $DEPLOY_DIR" && exit 1) + cd "$DEPLOY_DIR" + test -f "$COMPOSE_FILE" || (echo "❌ $COMPOSE_FILE not found in $DEPLOY_DIR" && exit 1) + test -f .env || (echo "❌ .env not found in $DEPLOY_DIR" && exit 1) # ✅ load env dari server - - set -a - - . ./.env - - set +a + set -a + . ./.env + set +a - # ✅ pastikan DB env ada - - test -n "$DB_HOST" || (echo "❌ DB_HOST empty" && exit 1) - - test -n "$DB_PORT" || (echo "❌ DB_PORT empty" && exit 1) - - test -n "$DB_USER" || (echo "❌ DB_USER empty" && exit 1) - - test -n "$DB_PASSWORD" || (echo "❌ DB_PASSWORD empty" && exit 1) - - test -n "$DB_NAME" || (echo "❌ DB_NAME empty" && exit 1) + # ✅ validasi + test -n "$DB_HOST" || (echo "❌ DB_HOST empty" && exit 1) + test -n "$DB_PORT" || (echo "❌ DB_PORT empty" && exit 1) + test -n "$DB_USER" || (echo "❌ DB_USER empty" && exit 1) + test -n "$DB_PASSWORD" || (echo "❌ DB_PASSWORD empty" && exit 1) + test -n "$DB_NAME" || (echo "❌ DB_NAME empty" && exit 1) - # ✅ generate DATABASE_URL - - export DATABASE_URL="postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=${DB_SSLMODE:-disable}" - - echo "✅ DATABASE_URL=$DATABASE_URL" + export DATABASE_URL="postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=${DB_SSLMODE:-disable}" + echo "✅ DATABASE_URL=$DATABASE_URL" - # ✅ pastikan postgres container hidup supaya network exist - - echo "✅ Ensuring postgres & redis running ..." - - docker compose -f "$COMPOSE_FILE" up -d postgres-sso redis-sso || true - # NOTE: ganti postgres-sso/redis-sso sesuai nama service di docker-compose lti kamu: - # kalau lti compose pakai stg-postgres-lti / stg-redis-lti, ganti di line ini. + # ✅ Pastikan postgres & redis ON (sesuaikan nama service compose kamu!) + echo "✅ Ensuring postgres & redis running ..." + docker compose -f "$COMPOSE_FILE" up -d stg-postgres-lti stg-redis-lti || true - # ✅ ambil network name compose (1st network) - - export COMPOSE_NETWORK="$(docker compose -f "$COMPOSE_FILE" config | awk '/networks:/ {getline; print $1}' | tr -d ':')" - - echo "✅ Compose network key: $COMPOSE_NETWORK" + # ✅ Ambil network key dari compose + COMPOSE_NETWORK_KEY="$(docker compose -f "$COMPOSE_FILE" config | awk '/networks:/ {getline; print $1}' | tr -d ':')" + echo "✅ Compose network key: $COMPOSE_NETWORK_KEY" - # ✅ ambil nama network aktual di docker (prefix foldername_) - - export NETWORK_NAME="$(docker network ls --format '{{.Name}}' | grep "_${COMPOSE_NETWORK}$" | head -n 1)" - - test -n "$NETWORK_NAME" || (echo "❌ Cannot find docker network for compose ($COMPOSE_NETWORK)" && exit 1) - - echo "✅ Docker network detected: $NETWORK_NAME" + # ✅ Cari network name yang dipakai docker + NETWORK_NAME="$(docker network ls --format '{{.Name}}' | grep "_${COMPOSE_NETWORK_KEY}$" | head -n 1)" + test -n "$NETWORK_NAME" || (echo "❌ Cannot find docker network for compose ($COMPOSE_NETWORK_KEY)" && exit 1) - # ✅ migrations dari repo (CI workspace) - - echo "✅ Checking migrations from repo..." - - ls -lah "$CI_PROJECT_DIR/internal/database/migrations" + echo "✅ Docker network detected: $NETWORK_NAME" - # ✅ run migrate (JOIN NETWORK) - - echo "✅ Running migrations via migrate/migrate container ..." - - set +e - - out=$(docker run --rm \ - --network "$NETWORK_NAME" \ - -v "$CI_PROJECT_DIR/internal/database/migrations:/migrations:ro" \ - migrate/migrate:v4.15.2 \ - -path=/migrations -database "$DATABASE_URL" up 2>&1) - - code=$? - - set -e + # ✅ Migrations dari repo (CI workspace) + echo "✅ Checking migrations from repo..." + ls -lah "$CI_PROJECT_DIR/internal/database/migrations" - - echo "$out" + echo "✅ Running migrations via migrate/migrate container" + set +e + out=$(docker run --rm \ + --network "$NETWORK_NAME" \ + -v "$CI_PROJECT_DIR/internal/database/migrations:/migrations:ro" \ + migrate/migrate:v4.15.2 \ + -path=/migrations -database "$DATABASE_URL" up 2>&1) + code=$? + set -e - # ✅ handle no change properly - - | - if echo "$out" | grep -qi "no change"; then - echo "✅ No change (already up to date)" - exit 0 - fi + echo "$out" - if [ $code -ne 0 ]; then - echo "❌ Migration failed with exit code $code" - exit $code - fi + # ✅ Handle no change dengan benar (tidak false-success) + if echo "$out" | grep -qi "no change"; then + echo "✅ No change (already up to date)" + exit 0 + fi + + if [ $code -ne 0 ]; then + echo "❌ Migration failed with exit code $code" + exit $code + fi + + echo "✅ Migration applied successfully" - echo "✅ Migration applied successfully" # ========================= # DEPLOY (AUTO) @@ -139,21 +137,22 @@ deploy_staging: artifacts: false - job: build_staging artifacts: false - script: - - set -e - - docker info - - echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY" + script: | + set -e + docker info + echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY" - - cd "$DEPLOY_DIR" - - test -f "$COMPOSE_FILE" || (echo "❌ $COMPOSE_FILE not found in $DEPLOY_DIR" && exit 1) - - test -f .env || (echo "❌ .env not found in $DEPLOY_DIR" && exit 1) + cd "$DEPLOY_DIR" + test -f "$COMPOSE_FILE" || (echo "❌ $COMPOSE_FILE not found in $DEPLOY_DIR" && exit 1) + test -f .env || (echo "❌ .env not found in $DEPLOY_DIR" && exit 1) + + docker compose -f "$COMPOSE_FILE" pull + docker compose -f "$COMPOSE_FILE" up -d --force-recreate + docker image prune -f - - docker compose -f "$COMPOSE_FILE" pull - - docker compose -f "$COMPOSE_FILE" up -d --force-recreate - - docker image prune -f # ========================= -# SEED (MANUAL) - OPTIONAL +# SEED (MANUAL) # ========================= seed_staging: stage: seed @@ -164,11 +163,11 @@ seed_staging: artifacts: false when: manual allow_failure: false - script: - - set -e - - cd "$DEPLOY_DIR" - - test -f "$COMPOSE_FILE" || (echo "❌ $COMPOSE_FILE not found" && exit 1) - - test -f .env || (echo "❌ .env not found" && exit 1) + script: | + set -e + cd "$DEPLOY_DIR" + test -f "$COMPOSE_FILE" || (echo "❌ $COMPOSE_FILE not found" && exit 1) + test -f .env || (echo "❌ .env not found" && exit 1) - - docker compose -f "$COMPOSE_FILE" pull seed || true - - docker compose -f "$COMPOSE_FILE" run --rm seed + docker compose -f "$COMPOSE_FILE" pull seed || true + docker compose -f "$COMPOSE_FILE" run --rm seed \ No newline at end of file