chore: add GitLab CI pipeline with build, container registry push, and deploy stages
This commit is contained in:
+157
@@ -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'
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
FROM amazoncorretto:21-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ARG JAR_FILE
|
||||||
|
COPY ${JAR_FILE} app.jar
|
||||||
|
|
||||||
|
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||||
Reference in New Issue
Block a user