Compare commits

...

15 Commits

Author SHA1 Message Date
kris 1f003c512d Update .gitlab-ci.yml file 2025-12-17 08:12:29 +00:00
kris 3ca95750a7 Update .gitlab-ci.yml file 2025-12-17 08:04:18 +00:00
kris 5dd2dbfa98 Update .gitlab-ci.yml file 2025-12-15 05:15:55 +00:00
M1 AIR 00bfd5ca45 . 2025-12-15 12:10:54 +07:00
M1 AIR 3e8bcb3f64 . 2025-12-15 12:08:24 +07:00
M1 AIR cfc4846170 . 2025-12-15 12:06:30 +07:00
M1 AIR c8f96c6086 . 2025-12-15 12:00:46 +07:00
M1 AIR 930fe25589 . 2025-12-15 11:54:55 +07:00
M1 AIR 4137008b92 . 2025-12-15 11:52:02 +07:00
kris 477f65554e Update .gitlab-ci.yml file 2025-12-15 04:50:12 +00:00
M1 AIR 6fcbcfd554 . 2025-12-15 11:43:37 +07:00
M1 AIR 99c34c5793 . 2025-12-15 11:37:11 +07:00
M1 AIR ecc9a51ea7 . 2025-12-15 11:34:45 +07:00
M1 AIR 75ade0d8b3 . 2025-12-15 11:32:43 +07:00
GitLab Deploy Bot b6a60d5009 remove 2025-12-15 09:25:50 +07:00
7 changed files with 80 additions and 322 deletions
-13
View File
@@ -1,13 +0,0 @@
# .air.toml
root = "."
tmp_dir = "tmp"
[build]
cmd = "go build -o ./tmp/main ./cmd/api"
bin = "tmp/main"
full_bin = "APP_ENV=dev ./tmp/main"
include_ext = ["go", "tpl", "tmpl", "html"]
exclude_dir = ["vendor", "tmp"]
[log]
time = true
+54 -73
View File
@@ -1,90 +1,71 @@
stages: stages:
- build
- deploy - deploy
deploy-dev: variables:
DOCKER_BUILDKIT: "1"
DOCKER_DRIVER: overlay2
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
IMAGE_TAG: "stg-ec2_${CI_COMMIT_SHORT_SHA}"
IMAGE_NAME: "${CI_REGISTRY_IMAGE}:${IMAGE_TAG}"
IMAGE_LATEST_STG_EC2: "${CI_REGISTRY_IMAGE}:stg-ec2_latest"
build:stg-ec2:
stage: build
image: docker:27.0.3
services:
- name: docker:27.0.3-dind
command: ["--mtu=1460"]
rules:
- if: '$CI_COMMIT_BRANCH == "stg-ec2"'
before_script:
- docker info
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
script:
- 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:stg-ec2:
stage: deploy stage: deploy
image: alpine:3.20 image: alpine:3.20
variables: rules:
DEPLOY_APP: "LTI-MBUGROUP" - if: '$CI_COMMIT_BRANCH == "stg-ec2"'
# Opsional: kalau pakai submodule, ini bikin clone submodule pakai SSH juga needs:
GIT_SUBMODULE_STRATEGY: recursive - job: build:stg-ec2
GIT_DEPTH: "1"
before_script: before_script:
- echo "🧰 Installing dependencies..." - apk add --no-cache openssh-client bash ca-certificates
- apk update && apk add --no-cache openssh git curl bash
# Setup SSH di runner
- mkdir -p ~/.ssh - mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa - chmod 700 ~/.ssh
# SSH_PRIVATE_KEY = multiline private key (bukan File)
- printf "%s\n" "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- sed -i 's/\r$//' ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa
- head -n 1 ~/.ssh/id_rsa
- tail -n 1 ~/.ssh/id_rsa
- eval "$(ssh-agent -s)" - eval "$(ssh-agent -s)"
- ssh-add ~/.ssh/id_rsa - ssh-add ~/.ssh/id_rsa
# Trust host keys (server + gitlab) biar SSH gak nanya interaktif
- ssh-keyscan -H "$SERVER_IP" >> ~/.ssh/known_hosts - ssh-keyscan -H "$SERVER_IP" >> ~/.ssh/known_hosts
- ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts
script: script:
- echo "🚀 Deploying latest code to $SERVER_USER@$SERVER_IP"
- > - >
if ssh -o StrictHostKeyChecking=no "$SERVER_USER@$SERVER_IP" " ssh "$SERVER_USER@$SERVER_IP"
set -e "export CI_REGISTRY_USER='$CI_REGISTRY_USER';
export CI_REGISTRY_PASSWORD='$CI_REGISTRY_PASSWORD';
cd /home/devops/docker/deployment/development/lti-api export CI_REGISTRY='$CI_REGISTRY';
set -e;
# Pastikan remote origin SSH (antisipasi kalau pernah ke-set HTTPS) cd /home/ubuntu/docker/deployment/staging/stg-lti-api;
git remote set-url origin git@gitlab.com:mbugroup/lti-api.git echo \"\$CI_REGISTRY_PASSWORD\" | docker login -u \"\$CI_REGISTRY_USER\" --password-stdin \"\$CI_REGISTRY\";
docker compose pull;
# Pastikan server percaya gitlab.com juga (untuk git fetch via SSH) docker compose up -d;
mkdir -p ~/.ssh docker image prune -f"
ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts
# Fetch/reset pakai SSH
GIT_SSH_COMMAND='ssh -o StrictHostKeyChecking=no' git fetch origin development
git reset --hard origin/development
docker compose restart dev-api-lti || docker compose up -d dev-api-lti
"; then
STATUS='success';
else
STATUS='failed';
fi;
RUN_URL="${CI_PROJECT_URL}/-/pipelines/${CI_PIPELINE_ID}";
if [ "$STATUS" = "success" ]; then
COLOR=3066993;
TITLE="✅ Deployment API Succeeded";
DESC="Deployment job on branch \`${CI_COMMIT_REF_NAME}\` completed successfully.";
else
COLOR=15158332;
TITLE="❌ Deployment API Failed Gaes";
DESC="Deployment job on branch \`${CI_COMMIT_REF_NAME}\` failed.";
fi;
echo "{
\"username\": \"CI Bot\",
\"embeds\": [{
\"title\": \"$TITLE\",
\"description\": \"$DESC\",
\"color\": $COLOR,
\"fields\": [
{\"name\": \"Repository\", \"value\": \"${CI_PROJECT_PATH}\", \"inline\": true},
{\"name\": \"Actor\", \"value\": \"${GITLAB_USER_LOGIN}\", \"inline\": true},
{\"name\": \"Commit\", \"value\": \"${CI_COMMIT_SHA}\", \"inline\": false},
{\"name\": \"Pipeline\", \"value\": \"[Open run](${RUN_URL})\", \"inline\": false}
]
}]
}" > payload.json;
echo "📡 Sending notification to Discord...";
curl -sS -H "Content-Type: application/json" \
-d @payload.json "$DISCORD_WEBHOOK_URL";
only:
- development
environment: environment:
name: development name: staging
+26 -11
View File
@@ -1,20 +1,35 @@
FROM golang:1.23-alpine # =========================
# Builder stage
# =========================
FROM golang:1.23-alpine AS builder
# Install dependensi dasar RUN apk add --no-cache git ca-certificates tzdata
RUN apk add --no-cache git curl bash build-base WORKDIR /app
# Install Air (pakai repo baru air-verse)
RUN go install github.com/air-verse/air@v1.52.3
WORKDIR /lti-api
# Cache dependencies
COPY go.mod go.sum ./ COPY go.mod go.sum ./
RUN go mod download RUN go mod download
# Copy source code
COPY . . COPY . .
# Build binary dari cmd/api
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -trimpath -ldflags="-s -w" -o lti-api ./cmd/api
# =========================
# Runtime stage
# =========================
FROM alpine:3.20
RUN apk add --no-cache ca-certificates tzdata curl \
&& adduser -D -H -u 10001 appuser
WORKDIR /app
COPY --from=builder /app/lti-api /app/lti-api
USER appuser
# Samakan dengan APP_PORT default kamu (8081)
EXPOSE 8081 EXPOSE 8081
CMD ["air", "-c", ".air.toml"] CMD ["/app/lti-api"]
-3
View File
@@ -1,3 +0,0 @@
POSTGRES_USER=postgres
POSTGRES_PASSWORD=Postgres@Secure2025!
POSTGRES_DB=db_lti_erp
-47
View File
@@ -1,47 +0,0 @@
-- ============================================================
-- 🧩 INIT SCRIPT: CREATE LIMITED APP USER FOR LTI API
-- ============================================================
-- Buat user aplikasi jika belum ada
DO
$$
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'app_lti_user') THEN
CREATE ROLE app_lti_user WITH LOGIN PASSWORD 'AppLti@Secure2025!' NOINHERIT NOCREATEROLE NOCREATEDB NOSUPERUSER;
RAISE NOTICE '✅ Role app_lti_user created successfully.';
ELSE
RAISE NOTICE '️ Role app_lti_user already exists.';
END IF;
END
$$;
-- Buat database jika belum ada
DO
$$
BEGIN
IF NOT EXISTS (SELECT FROM pg_database WHERE datname = 'db_lti_erp') THEN
CREATE DATABASE db_lti_erp OWNER app_lti_user;
RAISE NOTICE '✅ Database db_lti_erp created and owned by app_lti_user.';
ELSE
RAISE NOTICE '️ Database db_lti_erp already exists.';
END IF;
END
$$;
\connect db_lti_erp
-- Beri hak CRUD untuk app_lti_user
GRANT CONNECT ON DATABASE db_lti_erp TO app_lti_user;
GRANT USAGE ON SCHEMA public TO app_lti_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_lti_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_lti_user;
-- Set default privileges agar tabel baru juga bisa diakses
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_lti_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO app_lti_user;
-- Tampilkan hasil
\du app_lti_user
-77
View File
@@ -1,77 +0,0 @@
services:
postgresdb:
image: postgres:alpine
restart: always
ports:
- "${DB_PORT_HOST:-5542}:5432"
environment:
POSTGRES_USER: ${DB_USER:-postgres}
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
POSTGRES_DB: ${DB_NAME:-db_lti_erp}
volumes:
- dbdata:/var/lib/postgresql/data
- ./internal/database/init:/docker-entrypoint-initdb.d
networks: [go-network]
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-db_lti_erp}",
]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
restart: unless-stopped
ports:
- "${REDIS_PORT_HOST:-6381}:6379"
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
interval: 5s
timeout: 3s
retries: 10
networks: [go-network]
app:
build:
context: .
dockerfile: Dockerfile.local
image: cosmtrek/air:v1.52.3
working_dir: /lti-api
volumes:
- .:/lti-api
- ./internal/config/jwtRS256.key:/run/keys/jwtRS256.key
- ./internal/config/jwtRS256.key.pub:/run/keys/jwtRS256.key.pub
command: air -c .air.toml
env_file:
- .env
environment:
DB_HOST: postgresdb
DB_PORT: 5432
DB_USER: ${DB_USER:-postgres}
DB_PASSWORD: ${DB_PASSWORD:-postgres}
DB_NAME: ${DB_NAME:-db_lti_erp}
REDIS_URL: ${REDIS_URL:-redis://redis:6379/0}
ports:
- "${APP_PORT:-8081}:8081"
depends_on:
postgresdb:
condition: service_healthy
networks: [go-network]
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8081/healthz || exit 1"]
interval: 10s
timeout: 3s
retries: 10
start_period: 10s
volumes:
dbdata:
go-mod-cache:
go-build-cache:
networks:
go-network:
name: lti-api_go-network
driver: bridge
-98
View File
@@ -1,98 +0,0 @@
services:
dev-api-lti:
build:
context: .
dockerfile: Dockerfile
container_name: dev-api-lti
working_dir: /lti-api
command: ["/bin/sh", "scripts/entrypoint.sh"]
ports:
- "8081:8081"
env_file:
- .env
environment:
# override agar koneksi ke container internal
DB_HOST: dev-postgres-lti
DB_PORT: 5432
REDIS_URL: redis://dev-redis-lti:6379/0
volumes:
- .:/lti-api
- ./.air.toml:/lti-api/.air.toml:ro
- ./internal/config/jwtRS256.key:/run/keys/jwtRS256.key
- ./internal/config/jwtRS256.key.pub:/run/keys/jwtRS256.key.pub
depends_on:
- dev-postgres-lti
- dev-redis-lti
networks:
- lti-network
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8081/healthz || exit 1"]
interval: 10s
timeout: 3s
retries: 10
start_period: 10s
deploy:
resources:
limits:
cpus: "2.0"
memory: 2G
reservations:
cpus: "1.0"
memory: 512M
dev-postgres-lti:
image: postgres:15-alpine
container_name: dev-postgres-lti
restart: always
env_file:
- credential/.env.db
ports:
- "5433:5432"
volumes:
- dev-postgres-lti-data:/var/lib/postgresql/data
- ./credential:/docker-entrypoint-initdb.d:ro
networks:
- lti-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-db_lti_erp}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 5s
deploy:
resources:
limits:
cpus: "1.0"
memory: 2G
reservations:
cpus: "0.5"
memory: 512M
dev-redis-lti:
image: redis:7-alpine
container_name: dev-redis-lti
restart: always
ports:
- "6380:6379"
networks:
- lti-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 10
deploy:
resources:
limits:
cpus: "0.5"
memory: 512M
reservations:
cpus: "0.2"
memory: 256M
networks:
lti-network:
driver: bridge
volumes:
dev-postgres-lti-data: