chore: add GitLab CI pipeline with build, container registry push, and deploy stages

This commit is contained in:
2026-05-18 17:07:34 +08:00
parent 20d2edc9b1
commit 24b7913908
2 changed files with 164 additions and 0 deletions
+157
View File
@@ -0,0 +1,157 @@
stages:
- package
- build-image
- push
- deploy
variables:
# ---------- Gradle ----------
GRADLE_IMAGE: gradle:8.14.4-jdk21
GRADLE_USER_HOME: ${CI_PROJECT_DIR}/.gradle
# ---------- Docker ----------
DOCKER_IMAGE: docker:27.5.1
DOCKER_SERVICE: docker:27.5.1-dind
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
# ---------- Application ----------
APP_NAME: delta-force-guide-server
# ---------- Image tags ----------
IMAGE_TAG: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}
LATEST_TAG: ${CI_REGISTRY_IMAGE}:latest
# ---------- CI Dockerfile ----------
CI_DOCKERFILE: Dockerfile.ci
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .gradle/wrapper
- .gradle/caches
policy: pull-push
# ====================================================================
# Reusable template for Docker jobs
# ====================================================================
.docker:
image: ${DOCKER_IMAGE}
services:
- name: ${DOCKER_SERVICE}
command: ["--tls=false"]
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
# Trigger the pipeline for MRs, the default branch, and tags
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- if: '$CI_COMMIT_TAG'
# ====================================================================
# Stage 1 — Package: build the JAR with Gradle
# ====================================================================
package:
stage: package
image: ${GRADLE_IMAGE}
script:
- ./gradlew build
artifacts:
name: "${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}"
paths:
- build/libs/*.jar
expire_in: 1 hour
# ====================================================================
# Stage 2 — Build Docker image using the pre-built JAR artifact
# ====================================================================
build-image:
stage: build-image
extends: .docker
script:
# Resolve the actual JAR path
- JAR_FILE=$(ls build/libs/delta-force-guide-server-*.jar | head -1)
- echo "Packaging JAR: ${JAR_FILE}"
# Build image with the CI-specific single-stage Dockerfile
- |
docker build \
--build-arg JAR_FILE="${JAR_FILE}" \
-f ${CI_DOCKERFILE} \
-t ${IMAGE_TAG} \
-t ${LATEST_TAG} \
.
# Save the image as a CI artefact for the next stage
- docker save ${IMAGE_TAG} ${LATEST_TAG} > image.tar
artifacts:
paths:
- image.tar
expire_in: 1 hour
needs:
- package
# ====================================================================
# Stage 3 — Push image to GitLab Container Registry
# ====================================================================
push:
stage: push
extends: .docker
script:
- docker load < image.tar
- docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
- docker push ${IMAGE_TAG}
- docker push ${LATEST_TAG}
needs:
- build-image
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- if: '$CI_COMMIT_TAG'
# ====================================================================
# Stage 4 — Deploy on the target server via SSH
# ====================================================================
deploy:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client
- eval "$(ssh-agent -s)"
- echo "${DEPLOY_SSH_PRIVATE_KEY}" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
script:
- |
ssh -o StrictHostKeyChecking=no ${DEPLOY_USER}@${DEPLOY_HOST} "
set -e
echo '=== Pulling image ==='
echo ${CI_REGISTRY_PASSWORD} | docker login -u ${CI_REGISTRY_USER} --password-stdin ${CI_REGISTRY}
docker pull ${IMAGE_TAG}
echo '=== Stopping old container ==='
docker stop ${APP_NAME} || true
docker rm ${APP_NAME} || true
echo '=== Starting new container ==='
docker run -d \
--name ${APP_NAME} \
--restart unless-stopped \
-p ${DEPLOY_PORT:-8080}:8080 \
${IMAGE_TAG}
echo '=== Cleaning up old images ==='
docker image prune -f
echo '=== Deployment complete ==='
"
needs:
- push
environment:
name: production
url: http://${DEPLOY_HOST}:${DEPLOY_PORT:-8080}
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+7
View File
@@ -0,0 +1,7 @@
FROM amazoncorretto:21-alpine
WORKDIR /app
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]