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