mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-23 14:55:42 +00:00
penyesuaian flow cicid
This commit is contained in:
+129
-51
@@ -1,71 +1,149 @@
|
|||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
|
- migrate
|
||||||
- deploy
|
- deploy
|
||||||
|
- seed
|
||||||
|
|
||||||
|
default:
|
||||||
|
tags:
|
||||||
|
- self-hosted-stg
|
||||||
|
|
||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "staging"'
|
||||||
|
when: always
|
||||||
|
- when: never
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
DOCKER_BUILDKIT: "1"
|
DOCKER_BUILDKIT: "1"
|
||||||
DOCKER_DRIVER: overlay2
|
|
||||||
DOCKER_HOST: tcp://docker:2375
|
|
||||||
DOCKER_TLS_CERTDIR: ""
|
|
||||||
|
|
||||||
IMAGE_TAG: "staging_${CI_COMMIT_SHORT_SHA}"
|
IMAGE_TAG: "staging_${CI_COMMIT_SHORT_SHA}"
|
||||||
IMAGE_NAME: "${CI_REGISTRY_IMAGE}:${IMAGE_TAG}"
|
IMAGE_NAME: "${CI_REGISTRY_IMAGE}:${IMAGE_TAG}"
|
||||||
IMAGE_LATEST_STG_EC2: "${CI_REGISTRY_IMAGE}:staging_latest"
|
IMAGE_LATEST: "${CI_REGISTRY_IMAGE}:staging_latest"
|
||||||
|
DEPLOY_DIR: "/opt/deploy/stg-lti-api"
|
||||||
|
|
||||||
build:staging:
|
# =========================
|
||||||
|
# BUILD (AUTO)
|
||||||
|
# =========================
|
||||||
|
build_staging:
|
||||||
stage: build
|
stage: build
|
||||||
image: docker:27.0.3
|
|
||||||
services:
|
|
||||||
- name: docker:27.0.3-dind
|
|
||||||
command: ["--mtu=1460"]
|
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH == "staging"'
|
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "staging"'
|
||||||
before_script:
|
script: |
|
||||||
- docker info
|
set -e
|
||||||
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
|
docker info
|
||||||
script:
|
echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
|
||||||
- docker build -t "$IMAGE_NAME" -f Dockerfile .
|
|
||||||
- docker push "$IMAGE_NAME"
|
|
||||||
- docker tag "$IMAGE_NAME" "$IMAGE_LATEST_STG_EC2"
|
|
||||||
- docker push "$IMAGE_LATEST_STG_EC2"
|
|
||||||
|
|
||||||
deploy:staging:
|
echo "✅ Build image: $IMAGE_NAME"
|
||||||
stage: deploy
|
docker build -t "$IMAGE_NAME" -f Dockerfile .
|
||||||
image: alpine:3.20
|
|
||||||
|
echo "✅ Push image: $IMAGE_NAME"
|
||||||
|
docker push "$IMAGE_NAME"
|
||||||
|
|
||||||
|
echo "✅ Tag latest: $IMAGE_LATEST"
|
||||||
|
docker tag "$IMAGE_NAME" "$IMAGE_LATEST"
|
||||||
|
docker push "$IMAGE_LATEST"
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# MIGRATE (AUTO) - migrations diambil dari repo GitLab
|
||||||
|
# =========================
|
||||||
|
migrate_staging:
|
||||||
|
stage: migrate
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH == "staging"'
|
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "staging"'
|
||||||
needs:
|
needs:
|
||||||
- job: build:staging
|
- job: build_staging
|
||||||
|
artifacts: false
|
||||||
|
script: |
|
||||||
|
set -e
|
||||||
|
|
||||||
before_script:
|
# ✅ Load env dari server (.env hanya ada di server)
|
||||||
- apk add --no-cache openssh-client bash ca-certificates
|
cd "$DEPLOY_DIR"
|
||||||
- mkdir -p ~/.ssh
|
test -f .env || (echo "❌ .env not found in $DEPLOY_DIR" && exit 1)
|
||||||
- chmod 700 ~/.ssh
|
set -a
|
||||||
|
. ./.env
|
||||||
|
set +a
|
||||||
|
|
||||||
# SSH_PRIVATE_KEY = multiline private key (bukan File)
|
# ✅ Generate DATABASE_URL dari DB_*
|
||||||
- printf "%s\n" "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
test -n "$DB_HOST" || (echo "❌ DB_HOST empty" && exit 1)
|
||||||
- sed -i 's/\r$//' ~/.ssh/id_rsa
|
test -n "$DB_PORT" || (echo "❌ DB_PORT empty" && exit 1)
|
||||||
- chmod 600 ~/.ssh/id_rsa
|
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)
|
||||||
|
|
||||||
- head -n 1 ~/.ssh/id_rsa
|
export DATABASE_URL="postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=${DB_SSLMODE:-disable}"
|
||||||
- tail -n 1 ~/.ssh/id_rsa
|
echo "✅ DATABASE_URL ready"
|
||||||
|
|
||||||
- eval "$(ssh-agent -s)"
|
# ✅ migrations dari repo
|
||||||
- ssh-add ~/.ssh/id_rsa
|
echo "✅ Checking migrations from repo..."
|
||||||
- ssh-keyscan -H "$SERVER_IP" >> ~/.ssh/known_hosts
|
ls -lah "$CI_PROJECT_DIR/internal/database/migrations"
|
||||||
|
|
||||||
script:
|
echo "✅ Running migrations via migrate/migrate container"
|
||||||
- >
|
set +e
|
||||||
ssh "$SERVER_USER@$SERVER_IP"
|
docker run --rm \
|
||||||
"export CI_REGISTRY_USER='$CI_REGISTRY_USER';
|
-v "$CI_PROJECT_DIR/internal/database/migrations:/migrations:ro" \
|
||||||
export CI_REGISTRY_PASSWORD='$CI_REGISTRY_PASSWORD';
|
migrate/migrate:v4.15.2 \
|
||||||
export CI_REGISTRY='$CI_REGISTRY';
|
-path=/migrations -database "$DATABASE_URL" up
|
||||||
set -e;
|
code=$?
|
||||||
cd /home/ubuntu/docker/deployment/staging/stg-lti-api;
|
set -e
|
||||||
echo \"\$CI_REGISTRY_PASSWORD\" | docker login -u \"\$CI_REGISTRY_USER\" --password-stdin \"\$CI_REGISTRY\";
|
|
||||||
docker compose pull;
|
|
||||||
docker compose up -d;
|
|
||||||
docker image prune -f"
|
|
||||||
|
|
||||||
environment:
|
if [ $code -eq 0 ]; then
|
||||||
name: staging
|
echo "✅ Migration applied successfully"
|
||||||
|
elif [ $code -eq 1 ]; then
|
||||||
|
echo "✅ No change (already up to date)"
|
||||||
|
else
|
||||||
|
echo "❌ Migration failed with exit code $code"
|
||||||
|
exit $code
|
||||||
|
fi
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# DEPLOY (AUTO)
|
||||||
|
# =========================
|
||||||
|
deploy_staging:
|
||||||
|
stage: deploy
|
||||||
|
rules:
|
||||||
|
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "staging"'
|
||||||
|
needs:
|
||||||
|
- job: migrate_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"
|
||||||
|
|
||||||
|
cd "$DEPLOY_DIR"
|
||||||
|
test -f docker-compose.yaml || (echo "❌ docker-compose.yaml not found in $DEPLOY_DIR" && exit 1)
|
||||||
|
test -f .env || (echo "❌ .env not found in $DEPLOY_DIR" && exit 1)
|
||||||
|
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d --force-recreate
|
||||||
|
docker image prune -f
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# SEED (MANUAL)
|
||||||
|
# =========================
|
||||||
|
seed_staging:
|
||||||
|
stage: seed
|
||||||
|
rules:
|
||||||
|
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "staging"'
|
||||||
|
needs:
|
||||||
|
- job: deploy_staging
|
||||||
|
artifacts: false
|
||||||
|
when: manual
|
||||||
|
allow_failure: false
|
||||||
|
script: |
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd "$DEPLOY_DIR"
|
||||||
|
test -f docker-compose.yaml || (echo "❌ docker-compose.yaml not found in $DEPLOY_DIR" && exit 1)
|
||||||
|
test -f .env || (echo "❌ .env not found in $DEPLOY_DIR" && exit 1)
|
||||||
|
|
||||||
|
echo "✅ Pull latest seed image"
|
||||||
|
docker compose pull seed || true
|
||||||
|
|
||||||
|
echo "🌱 Running seeder..."
|
||||||
|
docker compose run --rm seed
|
||||||
|
|
||||||
|
echo "✅ Seed completed"
|
||||||
|
|||||||
+7
-4
@@ -11,25 +11,28 @@ RUN go mod download
|
|||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Build binary dari cmd/api
|
# Build API binary
|
||||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||||
go build -trimpath -ldflags="-s -w" -o lti-api ./cmd/api
|
go build -trimpath -ldflags="-s -w" -o lti-api ./cmd/api
|
||||||
|
|
||||||
|
# Build SEED binary (pastikan cmd/seed ada)
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||||
|
go build -trimpath -ldflags="-s -w" -o lti-seed ./cmd/seed
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Runtime stage
|
# Runtime stage
|
||||||
# =========================
|
# =========================
|
||||||
FROM alpine:3.20
|
FROM alpine:3.20
|
||||||
|
|
||||||
RUN apk add --no-cache ca-certificates tzdata curl \
|
RUN apk add --no-cache ca-certificates tzdata curl bash postgresql-client \
|
||||||
&& adduser -D -H -u 10001 appuser
|
&& adduser -D -H -u 10001 appuser
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY --from=builder /app/lti-api /app/lti-api
|
COPY --from=builder /app/lti-api /app/lti-api
|
||||||
|
COPY --from=builder /app/lti-seed /app/lti-seed
|
||||||
|
|
||||||
USER appuser
|
USER appuser
|
||||||
|
|
||||||
# Samakan dengan APP_PORT default kamu (8081)
|
|
||||||
EXPOSE 8081
|
EXPOSE 8081
|
||||||
|
|
||||||
CMD ["/app/lti-api"]
|
CMD ["/app/lti-api"]
|
||||||
Reference in New Issue
Block a user