Dokumentasi Teknis CI/CD

GitLab CI/CD Pipeline

Panduan lengkap otomasi build, test, quality assurance, security scanning, packaging, containerization, dan deployment aplikasi Spring Boot ke Kubernetes.

Stages

8

Environments

3

Databases

2

Security Tools

OWASP & SpotBugs

Project

molect-supra-core

Team

DAK SLDC

Last Updated

January 22, 2026

Docs

CI/CD

Visual alur pipeline dari build sampai deploy.

Pipeline Flow

Build → Deploy

End-to-end automation

Quality Gates

Coverage + Sonar

Maintain standards

Security

OWASP + SpotBugs

Proactive scanning

Delivery

Kaniko + K8s

Container-native

Gambaran Umum

Pipeline CI/CD ini dirancang untuk mengotomasi proses build, test, quality assurance, security scanning, packaging, containerization, dan deployment aplikasi Spring Boot ke Kubernetes cluster.

Fitur Utama

  • Automated Build & Test
  • Code Quality Analysis (SonarQube)
  • AI-Powered Code Review (Gemini)
  • Security Scanning (OWASP, SpotBugs)
  • Docker Image Building (Kaniko)
  • Multi-Environment Deployment (Dev, Staging, Production)
  • Database Flexibility (MySQL/PostgreSQL)
  • Kubernetes Native Deployment

Tech Stack

Build & Development Tools

Tool Versi Deskripsi
Maven 3.9.9 Build automation tool untuk Java
Java (Eclipse Temurin) 17 & 21 Java Development Kit (JDK)
Spring Boot - Framework aplikasi Java

Quality & Security Tools

Tool Deskripsi Stage
JaCoCo Code coverage analysis tool Test & Quality
SonarQube Platform analisis kualitas kode Quality
Gemini AI AI-powered code review Quality
OWASP Dependency Check Security vulnerability scanner untuk dependencies Security
SpotBugs Static analysis tool untuk bug detection Security

Container & Deployment

Tool Deskripsi
Kaniko Container image builder tanpa Docker daemon
Kubernetes (kubectl) Container orchestration platform
Docker Registry Private container registry (registry.e-gitlab.prodak.id)

Database Support

  • MySQL - Default database
  • PostgreSQL - Alternative database

Arsitektur Pipeline

Pipeline ini terdiri dari 8 stages yang berjalan secara sequential:

GITLAB CI/CD PIPELINE
Sequential flow

1. Build

Compile source code

Mengubah source Java menjadi bytecode yang siap diuji.

2. Test

Unit & integration tests

Menjamin fungsionalitas lewat unit dan integration test.

3. Quality

Coverage + Sonar + AI review

Memastikan kualitas kode lewat coverage, SonarQube, dan AI.

4. Security

OWASP + SpotBugs

Mendeteksi kerentanan dependency dan bug security.

5. Package

JAR/WAR artifacts

Membuat artifact siap rilis untuk tahap berikutnya.

6. Docker

Build & push image

Membangun image dan push ke private registry.

7. Deploy

Kubernetes rollout

Mendistribusikan aplikasi ke cluster Kubernetes.

Flow vertikal konsisten di semua ukuran layar.

Variabel Global

Maven Configuration

MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -XX:+TieredCompilation -XX:TieredStopAtLevel=1"
  • Fungsi: Optimasi performa Maven build
  • -Dmaven.repo.local: Set lokasi repository Maven lokal
  • -XX:+TieredCompilation: Enable tiered compilation JVM
  • -XX:TieredStopAtLevel=1: Optimasi untuk build cepat
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version"
  • --batch-mode: Jalankan Maven dalam mode non-interaktif
  • --errors: Tampilkan error messages
  • --fail-at-end: Build semua modul sebelum fail
  • --show-version: Tampilkan versi Maven

SonarQube Configuration

SONAR_HOST_URL: "${SONAR_HOST_URL:-http://sonarqube:9000}"
SONAR_LOGIN: "${SONAR_LOGIN:-}"
  • URL default SonarQube server
  • Token autentikasi (harus di-set di CI/CD Variables)

Docker Registry Configuration

DOCKER_REGISTRY: "registry.e-gitlab.prodak.id"
DOCKER_IMAGE_NAME: "${DOCKER_REGISTRY}/${CI_PROJECT_PATH}"
DOCKER_TLS_CERTDIR: "/certs"
  • Private Docker registry internal
  • Automatic image naming berdasarkan project path

Database Configuration

DATABASE_TYPE: "${DATABASE_TYPE:-mysql}"
  • Default: MySQL
  • Alternatif: PostgreSQL
  • Dapat di-override per environment

Cache Strategy

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .m2/repository/
    - target/
  policy: pull-push

Penjelasan

  • Key: Cache per-branch (menggunakan branch name)
  • Paths:
    • .m2/repository/: Maven dependencies
    • target/: Compiled classes dan artifacts
  • Policy: pull-push = Download cache di awal, upload di akhir

Benefit

  • Mempercepat build time (skip download dependencies yang sudah ada)
  • Menghemat bandwidth
  • Cache isolated per branch

Default Configuration

default:
  retry:
    max: 2
    when:
      - runner_system_failure
      - stuck_or_timeout_failure
      - api_failure
  timeout: 45 minutes
  tags:
    - ubuntu-runner

Retry Policy

  • Max retries: 2 kali
  • Kondisi retry: System failure, timeout, atau API failure

Timeout

Default timeout: 45 menit per job

Runner Tags

Menggunakan runner dengan tag ubuntu-runner

Stage: BUILD

Job: build

Tujuan: Compile source code Java menjadi bytecode

Docker Image

image: maven:3.9.9-eclipse-temurin-17-alpine
  • Maven 3.9.9
  • Java 17 (Eclipse Temurin distribution)
  • Alpine Linux (lightweight)

Before Script

  1. Setup Maven Settings
    mkdir -p ~/.m2
    cat <<EOF > ~/.m2/settings.xml

    Membuat file settings.xml untuk autentikasi ke GitLab Maven Registry menggunakan $CI_JOB_TOKEN.

  2. Install Local JAR Dependency
    mvn install:install-file \
      -Dfile=lib/com/dak/molect-supra-models/1.0.0/molect-supra-models-1.0.0.jar \
      -DpomFile=lib/com/dak/molect-supra-models/1.0.0/molect-supra-models-1.0.0.pom

    Install dependency molect-supra-models dari local lib folder karena tidak ada di Maven Central.

  3. Display Version Info
    • Maven version
    • Java version

Script

mvn $MAVEN_CLI_OPTS clean compile
  • clean: Hapus target folder
  • compile: Compile source code

Artifacts

artifacts:
  paths:
    - target/
  expire_in: 1 day
  when: on_success
  • Menyimpan folder target/ untuk digunakan stage berikutnya
  • Artifact expired dalam 1 hari
  • Hanya disimpan jika build success

Cache Policy

cache:
  policy: pull-push

Download dan upload cache

Stage: TEST

Job: test

Tujuan: Menjalankan unit test dan integration test, generate code coverage report

Dependencies

dependencies:
  - build

Menggunakan artifact dari job build

Script Logic

if [ -d "src/test/java" ]; then
  mvn $MAVEN_CLI_OPTS test
  mvn $MAVEN_CLI_OPTS jacoco:report
else
  echo "⚠️ No test directory found"
  mkdir -p target/surefire-reports
  mkdir -p target/site/jacoco
fi

Conditional Testing:

  • Cek apakah folder test exists
  • Jika ada: Jalankan test + generate JaCoCo report
  • Jika tidak ada: Skip test, buat folder dummy untuk compatibility

Artifacts

artifacts:
  when: always
  reports:
    junit: target/surefire-reports/TEST-*.xml
    coverage_report:
      coverage_format: cobertura
      path: target/site/jacoco/jacoco.xml
  paths:
    - target/surefire-reports/
    - target/site/jacoco/
  expire_in: 30 days

Test Reports:

  • JUnit: Test results dalam format XML
  • Coverage Report: Code coverage dalam format Cobertura
  • Artifact disimpan selama 30 hari
  • when: always = Simpan artifact meskipun test gagal

Coverage Display

coverage: '/Total.*?([0-9]{1,3})%/'

Regex untuk extract coverage percentage dan ditampilkan di GitLab MR/pipeline UI

Stage: QUALITY

Job 1: code_coverage_analysis

Tujuan: Analisis mendalam terhadap code coverage metrics

# Check if test directory exists
if [ ! -d "src/test/java" ]; then
  echo "⚠️ No test directory found"
  exit 0
fi

# Check if JaCoCo execution data exists
if [ -f target/jacoco.exec ]; then
  mvn $MAVEN_CLI_OPTS jacoco:report
fi

# Parse coverage percentage
COVERAGE=$(sed -n 's/.*line-rate="\([^"]*\)".*/\1/p' target/site/jacoco/jacoco.xml | head -1)
COVERAGE_PERCENT=$(echo "$COVERAGE * 100" | bc | cut -d. -f1)

# Warning if below threshold
if [ "$COVERAGE_PERCENT" -lt 60 ]; then
  echo "⚠️ Warning: Code coverage below 60% threshold"
fi

Coverage Threshold:

  • Warning Level: < 60%
  • Recommendation: Maintain coverage ≥ 60%
allow_failure: true

Job bisa gagal tanpa block pipeline (warning/monitoring)

Job 2: sonarqube_analysis

Tujuan: Static code analysis untuk detect bugs, code smells, dan security vulnerabilities

image: maven:3.9.9-eclipse-temurin-21-alpine

Menggunakan Java 21 (required by SonarQube scanner)

# Check if SONAR_LOGIN configured
if [ -z "$SONAR_LOGIN" ]; then
  echo "⚠️ Skipping SonarQube - SONAR_LOGIN not configured"
  exit 0
fi

# Conditional test parameter
if [ -d "src/test/java" ]; then
  TEST_PARAM="-Dsonar.tests=src/test/java"
else
  TEST_PARAM=""
fi

# Run SonarQube analysis
mvn $MAVEN_CLI_OPTS sonar:sonar \
  -Dsonar.projectKey=$CI_PROJECT_NAME \
  -Dsonar.projectName=$CI_PROJECT_NAME \
  -Dsonar.sources=src/main/java \
  $TEST_PARAM \
  -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml \
  -Dsonar.host.url=$SONAR_HOST_URL \
  -Dsonar.login=$SONAR_LOGIN

SonarQube Parameters

Parameter Deskripsi
projectKeyUnique identifier untuk project
projectNameDisplay name di SonarQube
sourcesSource code location
testsTest code location (optional)
coverage.jacoco.xmlReportPathsPath ke JaCoCo coverage report
host.urlSonarQube server URL
loginAuthentication token

Trigger Rules

only:
  - merge_requests
  - main
  - master
  - develop

Hanya berjalan pada MR dan main branches

Job 3: code_review

Tujuan: AI-powered code review menggunakan Gemini AI

image: python:3.11-slim

Python 3.11 untuk menjalankan Gemini review script

Before Script

  1. Install Dependencies
    apt-get update && apt-get install -y git
    git fetch --unshallow || git fetch --depth=50
  2. Clone Gemini Review Tool
    git clone https://oauth2:${GEMINI_REVIEW_TOKEN}@e-gitlab.prodak.id/dak-sldc/gemini-code-review.git /tmp/gemini-review
  3. Setup Virtual Environment
    python -m venv /tmp/gemini-review/venv
    source /tmp/gemini-review/venv/bin/activate
    pip install -r /tmp/gemini-review/requirements.txt
  4. Inject API Key
    export GEMINI_API_KEY="$GEMINI_API_KEY"

Script

git fetch --all
source /tmp/gemini-review/venv/bin/activate

python /tmp/gemini-review/src/main.py \
  --git-changes \
  --git-changes-from "$CI_COMMIT_BEFORE_SHA" \
  --git-changes-to "$CI_COMMIT_SHA" \
  --output-md code_review_report.md

Parameters:

  • --git-changes: Analyze only changed files
  • --git-changes-from: Start commit SHA
  • --git-changes-to: End commit SHA
  • --output-md: Output markdown report

Artifacts

artifacts:
  paths:
    - code_review_report.md
  expire_in: 7 days

Menyimpan code review report dalam markdown dan dapat diakses dari GitLab UI

Required Variables

  • GEMINI_REVIEW_TOKEN: Token untuk clone repository Gemini
  • GEMINI_API_KEY: API key untuk Gemini AI

Stage: SECURITY

Job 1: dependency_check

Tujuan: Scan dependencies untuk known security vulnerabilities (CVEs)

Tool: OWASP Dependency Check

  • Open source tool untuk detect CVEs
  • Database: National Vulnerability Database (NVD)
mvn $MAVEN_CLI_OPTS org.owasp:dependency-check-maven:check \
  -DassemblyAnalyzerEnabled=false \
  -DnodeAuditAnalyzerEnabled=false \
  -Dformat=HTML || true

Parameters:

  • assemblyAnalyzerEnabled=false: Disable .NET assembly analysis
  • nodeAuditAnalyzerEnabled=false: Disable Node.js audit
  • format=HTML: Output dalam format HTML

|| true: Job tidak fail meskipun ada vulnerabilities (untuk monitoring)

Artifacts

artifacts:
  paths:
    - target/dependency-check-report.html
  expire_in: 30 days

HTML report yang detail tentang vulnerabilities termasuk CVE ID, severity, dan recommended fixes

Trigger Rules

only:
  - main
  - master
  - develop
  - merge_requests

Job 2: spotbugs_analysis

Tujuan: Static analysis untuk detect bugs dan bad practices

Tool: SpotBugs

  • Successor dari FindBugs
  • Detect 400+ bug patterns
  • Categories: Correctness, Bad Practice, Performance, Security
mvn $MAVEN_CLI_OPTS compile spotbugs:spotbugs || true

if [ -f target/spotbugsXml.xml ]; then
  BUGS_COUNT=$(grep -c "BugInstance" target/spotbugsXml.xml || echo "0")
  echo "✅ SpotBugs analysis completed (found: ${BUGS_COUNT} issues)"
fi

Output: XML report dengan bug details

Bug Categories

  • Correctness: Logic errors
  • Bad Practice: Anti-patterns
  • Performance: Performance issues
  • Security: Security vulnerabilities
  • Dodgy Code: Confusing code

Artifacts

artifacts:
  paths:
    - target/spotbugsXml.xml
  expire_in: 30 days

Stage: PACKAGE

Job: package

Tujuan: Create executable JAR/WAR artifacts

Dependencies

dependencies:
  - build
  - test

Menggunakan compiled classes dari build dan memastikan test sudah passed

Script

mvn $MAVEN_CLI_OPTS package -DskipTests

JAR_FILE=$(find target -name "*.jar" -type f ! -name "*sources.jar" | head -1)
if [ -z "$JAR_FILE" ]; then
  echo "❌ Error: JAR file not found"
  exit 1
fi
echo "✅ JAR file created: $(basename $JAR_FILE)"
ls -lh "$JAR_FILE"

Process:

  1. package: Create JAR/WAR file
  2. -DskipTests: Skip test (sudah dijalankan di stage test)
  3. Validasi JAR file created successfully
  4. Display file size

Artifacts

artifacts:
  paths:
    - target/*.jar
    - target/*.war
  expire_in: 7 days
  when: on_success

Menyimpan JAR/WAR files sebagai artifact untuk Docker build stage

Trigger Rules

only:
  - main
  - master
  - develop
  - tags

Cache Policy

cache:
  policy: pull

Hanya download cache (tidak upload)

Stage: DOCKER

Job: docker_build

Tujuan: Build dan push Docker image ke private registry

Tool: Kaniko

  • Tidak perlu Docker daemon
  • Build container image inside container
  • Lebih secure (no privileged mode)
  • Kubernetes-native

Docker Image

image:
  name: gcr.io/kaniko-project/executor:debug
  entrypoint: [""]

Official Kaniko executor image (debug version)

Before Script: Docker Registry Auth

mkdir -p /kaniko/.docker
cat <<EOF > /kaniko/.docker/config.json
{
  "auths": {
    "registry.e-gitlab.prodak.id": {
      "username": "$CI_REGISTRY_USER",
      "password": "$CI_REGISTRY_PASSWORD"
    }
  }
}
EOF

Script: Multi-Tag Strategy

TAG_SHA="registry.e-gitlab.prodak.id/${CI_PROJECT_PATH}:${CI_COMMIT_SHORT_SHA}"
TAG_LATEST="registry.e-gitlab.prodak.id/${CI_PROJECT_PATH}:latest"
TAG_VERSION=""

if [ ! -z "$CI_COMMIT_TAG" ]; then
  TAG_VERSION="registry.e-gitlab.prodak.id/${CI_PROJECT_PATH}:${CI_COMMIT_TAG}"
fi

/kaniko/executor \
  --context "$CI_PROJECT_DIR" \
  --dockerfile "$CI_PROJECT_DIR/Dockerfile" \
  --destination "$TAG_SHA" \
  --destination "$TAG_LATEST" \
  ${TAG_VERSION:+--destination "$TAG_VERSION"} \
  --skip-tls-verify \
  --cache=true \
  --cache-repo="registry.e-gitlab.prodak.id/${CI_PROJECT_PATH}/cache"

Tag Strategy

Tag Type Format Purpose
SHA:abc1234Unique identifier per commit
Latest:latestAlways points to latest build
Version:v1.0.0Semantic versioning (for tags only)

Kaniko Parameters

Parameter Deskripsi
--contextBuild context (project directory)
--dockerfilePath ke Dockerfile
--destinationTarget registry dan tag
--skip-tls-verifySkip TLS verification (untuk self-signed cert)
--cache=trueEnable layer caching
--cache-repoRepository untuk cache layers

Benefits

  • Layer caching mempercepat rebuild
  • Multi-tag dalam satu build
  • Automatic push setelah build

Stage: DEPLOY

Deploy Template

Konsep: Reusable template untuk deploy ke berbagai environment

.deploy_template: &deploy_template
  stage: deploy
  image:
    name: bitnami/kubectl:latest
    entrypoint: [""]
  variables:
    DATABASE_TYPE: "${DATABASE_TYPE:-mysql}"

Kubernetes Image: bitnami/kubectl:latest (kubectl CLI tool)

Deploy Process Flow

KUBERNETES DEPLOYMENT FLOW
Sequential flow

1. Setup Kubeconfig

Inisialisasi akses cluster

Decode kubeconfig dan verifikasi koneksi ke cluster.

2. Create Namespace

Isolasi resource

Buat namespace molect-supra-core secara idempotent.

3. Registry Secret

Akses image private

Buat secret untuk pull image dari registry internal.

4. App Secrets

Kredensial aplikasi

Simpan username, password, dan JWT secret.

5. Deploy Database

MySQL/PostgreSQL

Deploy database sesuai konfigurasi environment.

6. Wait for Database

Readiness check

Tunggu sampai pod database berstatus Ready.

7. Deploy Application

Apply deployment

Apply manifest aplikasi ke namespace target.

8. Rollout Status

Observasi deployment

Monitor rollout hingga selesai atau timeout.

9. Display Status

Ringkasan hasil

Tampilkan pods, PVC, dan service untuk validasi.

Flow vertikal konsisten seperti UI Arsitektur Pipeline.

Before Script: Kubernetes Setup

# Set kubeconfig variable based on environment
KUBECONFIG_VAR="${KUBECONFIG_ENV}"
[ -z "$KUBECONFIG_VAR" ] && exit 0

# Decode and save kubeconfig
mkdir -p $HOME/.kube
echo "$KUBECONFIG_VAR" | base64 -d > $HOME/.kube/config
chmod 600 $HOME/.kube/config

# Test connection
kubectl cluster-info

Security:

  • Kubeconfig encoded dengan base64
  • File permission 600 (read/write owner only)
  • Test connection sebelum deploy

Script: Deployment Steps

1. Create Namespace

kubectl create namespace molect-supra-core --dry-run=client -o yaml | kubectl apply -f -
  • Idempotent: Create jika belum ada
  • --dry-run=client: Generate YAML tanpa create
  • kubectl apply: Apply YAML (create or update)

2. Create Registry Secret

kubectl delete secret registry-credentials -n molect-supra-core --ignore-not-found=true

kubectl create secret docker-registry registry-credentials \
  --docker-server=registry.e-gitlab.prodak.id \
  --docker-username=$CI_REGISTRY_USER \
  --docker-password=$CI_REGISTRY_PASSWORD \
  --docker-email="ci@gitlab.prodak.id" \
  -n molect-supra-core

Purpose: Kubernetes perlu credentials untuk pull private images

3. Create App Secrets

kubectl get secret app-secrets -n molect-supra-core 2>/dev/null || \
kubectl create secret generic app-secrets \
  --from-literal=DATASOURCE_USERNAME=spring_user \
  --from-literal=DATASOURCE_PASSWORD=spring_password \
  --from-literal=JWT_SECRET=MySecureJwtSecretKey12345678901234567890 \
  -n molect-supra-core

Secrets:

  • DATASOURCE_USERNAME: Database username
  • DATASOURCE_PASSWORD: Database password
  • JWT_SECRET: JWT signing key

Note: Ganti dengan values yang secure di production!

4. Deploy Database

if [ "$DATABASE_TYPE" = "mysql" ]; then
  echo "📦 Deploying MySQL infrastructure..."
  kubectl apply -f k8s-namespace-mysql.yaml
  kubectl apply -f k8s-configmap-mysql.yaml -n molect-supra-core
else
  echo "📦 Deploying PostgreSQL infrastructure..."
  kubectl apply -f k8s-configmap-postgres.yaml -n molect-supra-core
  kubectl apply -f k8s-postgres-deployment.yaml
fi

Database Selection:

  • MySQL: Default option
  • PostgreSQL: Alternative option
  • Determined by DATABASE_TYPE variable

5. Wait for Database Ready

for i in {1..30}; do
  [ "$DATABASE_TYPE" = "mysql" ] && POD_LABEL="mysql" || POD_LABEL="postgres"
  
  POD_STATUS=$(kubectl get pod -l app=$POD_LABEL -n molect-supra-core \
    -o jsonpath='{.items[0].status.conditions[?(@.type=="Ready")].status}' \
    2>/dev/null || echo "False")
  
  echo "Attempt $i/30 - Database status=$POD_STATUS"
  
  [ "$POD_STATUS" = "True" ] && echo "✅ Database ready!" && break
  
  sleep 10
done

Wait Logic:

  • Max 30 attempts (5 minutes)
  • Check every 10 seconds
  • Query pod ready condition
  • Break loop when ready

6. Deploy Application

kubectl apply -f k8s-deployment.yaml -n molect-supra-core

kubectl rollout status deployment/molect-supra-core \
  -n molect-supra-core \
  --timeout=5m || true

Rollout Status:

  • Wait up to 5 minutes for rollout complete
  • || true: Don't fail if timeout (will check status anyway)

7. Display Status

kubectl get pods -n molect-supra-core -o wide
kubectl get pvc -n molect-supra-core
kubectl get svc -n molect-supra-core

Information Displayed:

  • Pods: All running pods with node info
  • PVC: Persistent Volume Claims
  • Services: Network services and endpoints

Deploy Jobs

1. deploy_dev (Development)

deploy_dev:
  <<: *deploy_template
  variables:
    KUBECONFIG_ENV: "$KUBECONFIG_DEV"
    DATABASE_TYPE: "${DEV_DATABASE_TYPE:-mysql}"
  environment:
    name: development
    kubernetes:
      namespace: molect-supra-core
  only:
    - develop
  allow_failure: true
  • Trigger automatic pada branch develop
  • Kubeconfig: $KUBECONFIG_DEV
  • Database: Default MySQL, bisa override dengan DEV_DATABASE_TYPE
  • Allow Failure: Yes (development environment)

2. deploy_staging (Staging)

deploy_staging:
  <<: *deploy_template
  variables:
    KUBECONFIG_ENV: "$KUBECONFIG_STAGING"
    DATABASE_TYPE: "${STAGING_DATABASE_TYPE:-mysql}"
  environment:
    name: staging
    kubernetes:
      namespace: molect-supra-core
  only:
    - main
    - master
  when: manual
  allow_failure: true
  • Trigger manual pada branch main/master
  • Manual approval required
  • Purpose: Pre-production testing

3. deploy_prod (Production)

deploy_prod:
  <<: *deploy_template
  variables:
    KUBECONFIG_ENV: "$KUBECONFIG_PROD"
    DATABASE_TYPE: "${PROD_DATABASE_TYPE:-mysql}"
  before_script:
    - test -z "$CI_COMMIT_TAG" && echo "❌ Requires git tag" && exit 1
    # ... (standard before_script)
  environment:
    name: production
    kubernetes:
      namespace: molect-supra-core
  only:
    - tags
  when: manual
  allow_failure: true
  • Trigger manual, requires Git tag
  • Tag requirement ensures version control
  • Manual approval prevents accidental deploy

Konfigurasi Environment

Required GitLab CI/CD Variables

Registry Credentials

VariableTypeDescription
CI_REGISTRY_USERVariableDocker registry username
CI_REGISTRY_PASSWORDVariableDocker registry password

SonarQube

VariableTypeDescription
SONAR_HOST_URLVariableSonarQube server URL
SONAR_LOGINVariableSonarQube authentication token

Gemini Code Review

VariableTypeDescription
GEMINI_REVIEW_TOKENVariableToken untuk clone Gemini review repo
GEMINI_API_KEYVariableGemini AI API key

Kubernetes Credentials (Base64 Encoded)

VariableTypeDescription
KUBECONFIG_DEVFileDevelopment cluster kubeconfig
KUBECONFIG_STAGINGFileStaging cluster kubeconfig
KUBECONFIG_PRODFileProduction cluster kubeconfig

Database Selection (Optional)

VariableDefaultDescription
DATABASE_TYPEmysqlGlobal database type
DEV_DATABASE_TYPEmysqlDevelopment database
STAGING_DATABASE_TYPEmysqlStaging database
PROD_DATABASE_TYPEmysqlProduction database

Options: mysql atau postgresql

Cara Set Variables di GitLab

  1. Navigate ke Settings > CI/CD > Variables
  2. Click Add variable
  3. Set:
    • Key: Variable name
    • Value: Variable value
    • Type: Variable atau File
    • Protected: Yes (untuk production)
    • Masked: Yes (untuk sensitive data)

Example: Set Kubeconfig

# Encode kubeconfig to base64
cat ~/.kube/config | base64 -w 0 > kubeconfig.base64

# Copy content dari kubeconfig.base64
# Paste ke GitLab CI variable KUBECONFIG_PROD

Run Down Perancangan & Implementasi (12–26 Januari 2026)

Timeline berikut merangkum aktivitas perancangan dan implementasi CI/CD GitLab untuk project molect, termasuk setup infrastruktur, tools quality/security, trial & error pipeline, hingga dokumentasi akhir.

TIMELINE IMPLEMENTASI
12–26 Jan 2026

12 Jan 2026

Kickoff & Scope Alignment

  • Workshop kebutuhan pipeline (build, test, quality, security, deploy).
  • Definisi environment target (dev, staging, prod).
  • Inventarisasi dependency lokal & repository internal.

13–14 Jan 2026

Setup Infrastruktur Kubernetes

  • Provisioning cluster & namespace molect-supra-core.
  • Konfigurasi storage (PVC) & resource quotas.
  • Uji konektivitas kubeconfig untuk CI.

15 Jan 2026

GitLab Runner & Registry

  • Registrasi runner bertag ubuntu-runner.
  • Validasi akses registry private.
  • Uji job build sederhana untuk verifikasi runner.

16–17 Jan 2026

SonarQube & Quality Gate

  • Deploy SonarQube dan konfigurasi token akses.
  • Integrasi coverage JaCoCo ke Sonar.
  • Trial analysis di branch develop.

18 Jan 2026

Gemini AI Code Review

  • Integrasi repo gemini-code-review ke pipeline.
  • Setup GEMINI_REVIEW_TOKEN & GEMINI_API_KEY.
  • Validasi output report markdown.

19 Jan 2026

Security Scanning

  • OWASP Dependency Check & SpotBugs baseline.
  • Penetapan allow_failure: true untuk monitoring.
  • Review initial findings dan exclusions.

20 Jan 2026

Packaging & Artifact Management

  • Standarisasi packaging JAR/WAR.
  • Artifact retention & dependency cache tuning.
  • Validasi compatibility antar stage.

21 Jan 2026

Docker Build (Kaniko)

  • Konfigurasi Kaniko & multi-tag image.
  • Uji push ke registry private.
  • Optimasi layer cache.

22–23 Jan 2026

Trial & Error Deployment (Dev/Staging)

  • Debug kubeconfig, namespace, dan registry secret.
  • Validasi readiness database & rollout status.
  • Perbaikan manifest deployment & env vars.

24 Jan 2026

Stabilization & Pipeline Hardening

  • Refactor rules/only untuk MR & tag.
  • Retry policy & timeout tuning.
  • Finalisasi cache strategy.

25–26 Jan 2026

Dokumentasi & Handover

  • Finalisasi dokumentasi CI/CD, troubleshooting, dan best practices.
  • Review lint/format HTML & asset consistency.
  • Handover ke tim operasi & penjadwalan maintenance.

Catatan: Timeline bersifat ringkas untuk kebutuhan dokumentasi internal.

Best Practices

1. Branch Strategy

main/master    → Staging deployment
develop        → Dev deployment
tags (v*)      → Production deployment
feature/*      → Build + Test only

2. Security

  • Semua credentials di GitLab CI variables (encrypted)
  • Kubeconfig base64 encoded
  • Docker registry credentials protected
  • Production deployment requires git tag
  • Manual approval untuk staging/production

3. Performance Optimization

  • Maven cache untuk dependencies
  • Docker layer caching dengan Kaniko
  • Parallel jobs where possible
  • Artifact expiration untuk cleanup

4. Monitoring & Debugging

  • Coverage reports di GitLab UI
  • Test reports dalam JUnit format
  • Security scan reports (HTML)
  • Deployment status di Kubernetes

5. Failure Handling

  • Automatic retry untuk system failures
  • allow_failure: true untuk non-critical jobs
  • Detailed logging dengan indikator visual
  • Graceful handling untuk missing test directory

6. Database Management

  • Flexible database selection (MySQL/PostgreSQL)
  • Per-environment database configuration
  • Wait for database ready before app deployment
  • Persistent storage support

Troubleshooting

Build Failed: JAR Not Found

Symptom: ❌ JAR file not found!

Solution: Check lib/com/dak/molect-supra-models/ structure

SonarQube Analysis Skipped

Symptom: ⚠️ Skipping SonarQube - SONAR_LOGIN not configured

Solution: Set SONAR_LOGIN variable di GitLab CI/CD settings

Docker Push Failed

Symptom: unauthorized: authentication required

Solution: Verify CI_REGISTRY_USER dan CI_REGISTRY_PASSWORD variables

Deployment Failed: Kubeconfig

Symptom: error: loading kubeconfig

Solution:

  1. Verify kubeconfig encoded correctly (base64)
  2. Check KUBECONFIG_* variable exists
  3. Test kubeconfig locally:
echo "$KUBECONFIG_DEV" | base64 -d > test-config
kubectl --kubeconfig=test-config cluster-info
Database Not Ready

Symptom: Timeout waiting for database

Solution:

  1. Check pod status: kubectl get pods -n molect-supra-core
  2. Check pod logs: kubectl logs <pod-name> -n molect-supra-core
  3. Verify PVC bound: kubectl get pvc -n molect-supra-core

Maintenance

Update Maven Version

Edit image tag di semua jobs:

image: maven:3.9.9-eclipse-temurin-17-alpine
       # ↑ Update version number

Update Java Version

Edit Eclipse Temurin version:

image: maven:3.9.9-eclipse-temurin-21-alpine
       #                         ↑ Update Java version

Update Dependency

Update local JAR di before_script:

mvn install:install-file \
  -Dfile=lib/com/dak/molect-supra-models/2.0.0/molect-supra-models-2.0.0.jar \
  #                                     ↑ Update version

Resources

Official Documentation

Tools Documentation

Changelog

Version 1.0.0 (Current)

  • Complete CI/CD pipeline implementation
  • Multi-stage build process
  • Quality & security scanning
  • Kubernetes deployment automation
  • Multi-environment support
  • Flexible database selection

Support

Untuk pertanyaan atau issue terkait pipeline ini, hubungi:

  • Team: DAK SLDC
  • Project: molect-supra-core
  • GitLab: e-gitlab.prodak.id