Merge branch 'pipeline' into 'dev'
Gitlab CI/CD Pipeline See merge request rheinsw/rheinsw-mono-repo!1
This commit was merged in pull request #1.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,3 +7,5 @@
|
|||||||
/backend/discovery/target/
|
/backend/discovery/target/
|
||||||
/backend/gateway/target/
|
/backend/gateway/target/
|
||||||
/backend/server/target/
|
/backend/server/target/
|
||||||
|
|
||||||
|
*.env
|
||||||
|
|||||||
125
.gitlab-ci-template.yml
Normal file
125
.gitlab-ci-template.yml
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
.docker-login-template:
|
||||||
|
before_script:
|
||||||
|
- |
|
||||||
|
echo "Logging into Docker..."
|
||||||
|
echo "$CI_REGISTRY_PASSWORD" | docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" --password-stdin
|
||||||
|
|
||||||
|
.image-tag-template:
|
||||||
|
script: |
|
||||||
|
TAG="${CI_COMMIT_REF_NAME//\//_}"
|
||||||
|
DOCKER_IMAGE="$CI_REGISTRY/$CI_PROJECT_PATH/$IMAGE_NAME"
|
||||||
|
echo "Generated tag: $TAG"
|
||||||
|
echo "Docker image: $DOCKER_IMAGE:$TAG"
|
||||||
|
|
||||||
|
.docker-build-template:
|
||||||
|
extends: .docker-login-template
|
||||||
|
stage: dockerize
|
||||||
|
image: docker:20.10@sha256:2967f0819c84dd589ed0a023b9d25dcfe7a3c123d5bf784ffbb77edf55335f0c
|
||||||
|
script:
|
||||||
|
- !reference [ .image-tag-template, script ]
|
||||||
|
- |
|
||||||
|
echo "Building Docker image for $IMAGE_NAME in $WORKDIR_PATH"
|
||||||
|
cd $WORKDIR_PATH
|
||||||
|
|
||||||
|
BUILD_ARGS="--build-arg IMAGE_TAG=$TAG"
|
||||||
|
if [ -n "$COMMON_IMAGE" ]; then BUILD_ARGS="$BUILD_ARGS --build-arg COMMON_IMAGE=$COMMON_IMAGE:$TAG"; fi
|
||||||
|
if [ -n "$BUILD_FOLDER" ]; then BUILD_ARGS="$BUILD_ARGS --build-arg BUILD_FOLDER=$BUILD_FOLDER"; fi
|
||||||
|
if [ -n "$IMAGE_NAME" ]; then BUILD_ARGS="$BUILD_ARGS --build-arg IMAGE_NAME=$IMAGE_NAME"; fi
|
||||||
|
if [ -n "$MAIN_CLASS" ]; then BUILD_ARGS="$BUILD_ARGS --build-arg MAIN_CLASS=$MAIN_CLASS"; fi
|
||||||
|
docker build $BUILD_ARGS -t $DOCKER_IMAGE:$TAG -f $DOCKERFILE_PATH .
|
||||||
|
|
||||||
|
if [[ "$TAG" == "dev" || "$TAG" == "production" || "$TAG" == "pipeline" ]]; then
|
||||||
|
echo "Pushing Docker image $DOCKER_IMAGE:$TAG"
|
||||||
|
docker push $DOCKER_IMAGE:$TAG
|
||||||
|
|
||||||
|
# After pushing the image
|
||||||
|
DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' $DOCKER_IMAGE:$TAG | cut -d '@' -f2)
|
||||||
|
echo "$DIGEST" > "$CI_PROJECT_DIR/digest-${IMAGE_NAME}.txt"
|
||||||
|
echo "Digest for $IMAGE_NAME: $DIGEST"
|
||||||
|
else
|
||||||
|
echo "Skipping push for non-dev/non-production branch: $TAG"
|
||||||
|
fi
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- digest-*.txt
|
||||||
|
expire_in: 1 hour
|
||||||
|
|
||||||
|
# BUILD COMMON IMAGE
|
||||||
|
.docker-common-template:
|
||||||
|
extends: .docker-login-template
|
||||||
|
stage: docker-base
|
||||||
|
image: docker:20.10@sha256:2967f0819c84dd589ed0a023b9d25dcfe7a3c123d5bf784ffbb77edf55335f0c
|
||||||
|
script:
|
||||||
|
- !reference [ .image-tag-template, script ]
|
||||||
|
- |
|
||||||
|
echo "Building BASE Docker image for $IMAGE_NAME..."
|
||||||
|
cd $WORKDIR_PATH
|
||||||
|
docker build -f $DOCKERFILE_PATH -t $DOCKER_IMAGE:$TAG .
|
||||||
|
if [[ "$TAG" == "dev" || "$TAG" == "production" || "$TAG" == "pipeline" ]]; then
|
||||||
|
echo "Pushing Docker image $DOCKER_IMAGE:$TAG"
|
||||||
|
docker push $DOCKER_IMAGE:$TAG
|
||||||
|
else
|
||||||
|
echo "Skipping push for non-dev/non-production branch: $TAG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Deployment
|
||||||
|
.install-deploy-key: &install-deploy-key
|
||||||
|
- |
|
||||||
|
echo "Installing SSH deploy key..."
|
||||||
|
which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo "$DEPLOY_KEY_BASE64" | base64 -d > ~/.ssh/deploy_key
|
||||||
|
chmod 600 ~/.ssh/deploy_key
|
||||||
|
eval "$(ssh-agent -s)"
|
||||||
|
ssh-add ~/.ssh/deploy_key
|
||||||
|
if [[ "$TAG" == "dev" || "$TAG" == "pipeline" ]]; then
|
||||||
|
HOST="$DEPLOY_DEV_HOST"
|
||||||
|
PORT="${DEPLOY_DEV_PORT:-22}"
|
||||||
|
else
|
||||||
|
HOST="$DEPLOY_PROD_HOST"
|
||||||
|
PORT="${DEPLOY_PROD_PORT:-22}"
|
||||||
|
fi
|
||||||
|
echo "Scanning SSH host $HOST on port $PORT"
|
||||||
|
ssh-keyscan -p "$PORT" "$HOST" >> ~/.ssh/known_hosts || true
|
||||||
|
|
||||||
|
.deploy-template:
|
||||||
|
stage: deploy
|
||||||
|
image: docker:20.10@sha256:2967f0819c84dd589ed0a023b9d25dcfe7a3c123d5bf784ffbb77edf55335f0c
|
||||||
|
before_script:
|
||||||
|
- !reference [ .install-deploy-key ]
|
||||||
|
script: |
|
||||||
|
if [[ "$TAG" == "dev" || "$TAG" == "pipeline" ]]; then
|
||||||
|
HOST="$DEPLOY_DEV_HOST"
|
||||||
|
PORT="${DEPLOY_DEV_PORT:-22}"
|
||||||
|
else
|
||||||
|
HOST="$DEPLOY_PROD_HOST"
|
||||||
|
PORT="${DEPLOY_PROD_PORT:-22}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Image digests:"
|
||||||
|
echo " gateway : $(cat digest-gateway.txt)"
|
||||||
|
echo " server : $(cat digest-server.txt)"
|
||||||
|
echo " frontend : $(cat digest-frontend.txt)"
|
||||||
|
|
||||||
|
echo "Injecting image digests"
|
||||||
|
cp docker-compose.yml docker-compose.generated.yml
|
||||||
|
|
||||||
|
sed -i "s|registry.boomlab.party/rheinsw/rheinsw-mono-repo/gateway|registry.boomlab.party/rheinsw/rheinsw-mono-repo/gateway@$(cat digest-gateway.txt)|g" docker-compose.generated.yml
|
||||||
|
sed -i "s|registry.boomlab.party/rheinsw/rheinsw-mono-repo/server|registry.boomlab.party/rheinsw/rheinsw-mono-repo/server@$(cat digest-server.txt)|g" docker-compose.generated.yml
|
||||||
|
sed -i "s|registry.boomlab.party/rheinsw/rheinsw-mono-repo/frontend|registry.boomlab.party/rheinsw/rheinsw-mono-repo/frontend@$(cat digest-frontend.txt)|g" docker-compose.generated.yml
|
||||||
|
|
||||||
|
echo "Copying docker-compose.generated.yml to $HOST:$REMOTE_ENV_PATH/docker-compose.yml"
|
||||||
|
# Ensure remote path exists before scp
|
||||||
|
ssh -p "$PORT" "$DEPLOY_USER@$HOST" "mkdir -p $REMOTE_ENV_PATH"
|
||||||
|
|
||||||
|
# Copy
|
||||||
|
scp -P "$PORT" docker-compose.generated.yml "$DEPLOY_USER@$HOST:$REMOTE_ENV_PATH/docker-compose.yml"
|
||||||
|
|
||||||
|
echo "Deploying on $HOST"
|
||||||
|
ssh -p "$PORT" "$DEPLOY_USER@$HOST" "
|
||||||
|
cd $REMOTE_ENV_PATH
|
||||||
|
echo "$CI_REGISTRY_PASSWORD" | docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" --password-stdin
|
||||||
|
docker compose down || true
|
||||||
|
docker compose pull || true
|
||||||
|
docker compose up -d
|
||||||
|
"
|
||||||
56
.gitlab-ci.yml
Normal file
56
.gitlab-ci.yml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
image: docker:20.10@sha256:2967f0819c84dd589ed0a023b9d25dcfe7a3c123d5bf784ffbb77edf55335f0c
|
||||||
|
|
||||||
|
include:
|
||||||
|
- local: '.gitlab-ci-template.yml'
|
||||||
|
- local: 'backend/.gitlab-ci.yml'
|
||||||
|
- local: 'frontend/.gitlab-ci.yml'
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
- docker-base
|
||||||
|
- dockerize
|
||||||
|
- deploy
|
||||||
|
- sync
|
||||||
|
|
||||||
|
variables:
|
||||||
|
CI_REGISTRY_IMAGE: $CI_REGISTRY/$CI_PROJECT_PATH
|
||||||
|
PROJECT_NAME: $CI_PROJECT_NAME
|
||||||
|
# Next JS vars
|
||||||
|
NEXT_PUBLIC_ENV: "production"
|
||||||
|
OUTPUT_DIR: ".next"
|
||||||
|
|
||||||
|
.deploy_production_rule: &deploy_production_rule
|
||||||
|
- if: $CI_COMMIT_BRANCH == "production"
|
||||||
|
when: manual
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
|
sync_dev_branch:
|
||||||
|
stage: sync
|
||||||
|
image: node:22@sha256:f6b9c31ace05502dd98ef777aaa20464362435dcc5e312b0e213121dcf7d8b95
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_BRANCH == "production"'
|
||||||
|
before_script:
|
||||||
|
- git config --global user.email "gitlab-ci@rhein-software.dev"
|
||||||
|
- git config --global user.name "GitLab CI"
|
||||||
|
script:
|
||||||
|
- git remote set-url origin "https://oauth2:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git"
|
||||||
|
- git checkout dev
|
||||||
|
- git pull origin dev
|
||||||
|
- git merge --no-ff origin/production
|
||||||
|
- git push origin dev
|
||||||
|
|
||||||
|
deploy_dev:
|
||||||
|
extends: .deploy-template
|
||||||
|
variables:
|
||||||
|
TAG: '$CI_COMMIT_BRANCH'
|
||||||
|
REMOTE_ENV_PATH: /rheinsw/dev
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_BRANCH == "dev" || $CI_COMMIT_BRANCH == "pipeline"'
|
||||||
|
|
||||||
|
deploy_prod:
|
||||||
|
extends: .deploy-template
|
||||||
|
variables:
|
||||||
|
TAG: production
|
||||||
|
REMOTE_ENV_PATH: /rheinsw/prod
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_BRANCH == "production"'
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
|
||||||
<configuration default="false" name="DiscoveryServerApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
|
|
||||||
<module name="discovery" />
|
|
||||||
<option name="SPRING_BOOT_MAIN_CLASS" value="dev.rheinsw.discovery.DiscoveryServerApplication" />
|
|
||||||
<extension name="coverage">
|
|
||||||
<pattern>
|
|
||||||
<option name="PATTERN" value="dev.rheinsw.discovery.*" />
|
|
||||||
<option name="ENABLED" value="true" />
|
|
||||||
</pattern>
|
|
||||||
</extension>
|
|
||||||
<method v="2">
|
|
||||||
<option name="Make" enabled="true" />
|
|
||||||
</method>
|
|
||||||
</configuration>
|
|
||||||
</component>
|
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="GatewayApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
|
<configuration default="false" name="GatewayApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
|
||||||
|
<option name="envFilePaths">
|
||||||
|
<option value="$PROJECT_DIR$/gateway.env" />
|
||||||
|
</option>
|
||||||
<module name="gateway" />
|
<module name="gateway" />
|
||||||
|
<selectedOptions>
|
||||||
|
<option name="environmentVariables" />
|
||||||
|
</selectedOptions>
|
||||||
<option name="SPRING_BOOT_MAIN_CLASS" value="dev.rheinsw.gateway.GatewayApplication" />
|
<option name="SPRING_BOOT_MAIN_CLASS" value="dev.rheinsw.gateway.GatewayApplication" />
|
||||||
<extension name="coverage">
|
<extension name="coverage">
|
||||||
<pattern>
|
<pattern>
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="ServerApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
|
<configuration default="false" name="ServerApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
|
||||||
|
<option name="envFilePaths">
|
||||||
|
<option value="$PROJECT_DIR$/server.env" />
|
||||||
|
</option>
|
||||||
<module name="server" />
|
<module name="server" />
|
||||||
|
<selectedOptions>
|
||||||
|
<option name="environmentVariables" />
|
||||||
|
</selectedOptions>
|
||||||
<option name="SPRING_BOOT_MAIN_CLASS" value="dev.rheinsw.server.ServerApplication" />
|
<option name="SPRING_BOOT_MAIN_CLASS" value="dev.rheinsw.server.ServerApplication" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/backend/server" />
|
||||||
<extension name="coverage">
|
<extension name="coverage">
|
||||||
<pattern>
|
<pattern>
|
||||||
<option name="PATTERN" value="dev.rheinsw.server.*" />
|
<option name="PATTERN" value="dev.rheinsw.server.*" />
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
<script value="dev" />
|
<script value="dev" />
|
||||||
</scripts>
|
</scripts>
|
||||||
<node-interpreter value="project" />
|
<node-interpreter value="project" />
|
||||||
<envs />
|
<envs>
|
||||||
|
<env name="HCAPTCHA_SECRET" value="10000000-ffff-ffff-ffff-000000000001" />
|
||||||
|
</envs>
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
||||||
48
backend/.gitlab-ci.yml
Normal file
48
backend/.gitlab-ci.yml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
build_backend:
|
||||||
|
stage: build
|
||||||
|
image: maven:3.9.9-eclipse-temurin-21@sha256:2e3824afeb41f61761adee95318814e6669bd59aaf61255b2af47064b8755c02
|
||||||
|
script:
|
||||||
|
- cd backend
|
||||||
|
- mvn package
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- backend/common/target/
|
||||||
|
- backend/gateway/target/
|
||||||
|
- backend/discovery/target/
|
||||||
|
- backend/server/target
|
||||||
|
expire_in: 1 hour
|
||||||
|
|
||||||
|
docker_common:
|
||||||
|
extends: .docker-common-template
|
||||||
|
variables:
|
||||||
|
IMAGE_NAME: common
|
||||||
|
WORKDIR_PATH: backend
|
||||||
|
DOCKERFILE_PATH: Dockerfile.base
|
||||||
|
needs:
|
||||||
|
- build_backend
|
||||||
|
|
||||||
|
docker_gateway:
|
||||||
|
extends: .docker-build-template
|
||||||
|
variables:
|
||||||
|
IMAGE_NAME: gateway
|
||||||
|
COMMON_IMAGE: "$CI_REGISTRY/$CI_PROJECT_PATH/common"
|
||||||
|
WORKDIR_PATH: backend
|
||||||
|
DOCKERFILE_PATH: Dockerfile.app
|
||||||
|
BUILD_FOLDER: "gateway/target"
|
||||||
|
MAIN_CLASS: dev.rheinsw.gateway.GatewayApplication
|
||||||
|
needs:
|
||||||
|
- build_backend
|
||||||
|
- docker_common
|
||||||
|
|
||||||
|
docker_server:
|
||||||
|
extends: .docker-build-template
|
||||||
|
variables:
|
||||||
|
IMAGE_NAME: server
|
||||||
|
COMMON_IMAGE: "$CI_REGISTRY/$CI_PROJECT_PATH/common"
|
||||||
|
WORKDIR_PATH: backend
|
||||||
|
DOCKERFILE_PATH: Dockerfile.app
|
||||||
|
BUILD_FOLDER: "server/target"
|
||||||
|
MAIN_CLASS: dev.rheinsw.server.ServerApplication
|
||||||
|
needs:
|
||||||
|
- build_backend
|
||||||
|
- docker_common
|
||||||
32
backend/Dockerfile.app
Normal file
32
backend/Dockerfile.app
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# Dockerfile.app
|
||||||
|
|
||||||
|
ARG COMMON_IMAGE
|
||||||
|
FROM ${COMMON_IMAGE}
|
||||||
|
|
||||||
|
ARG BUILD_FOLDER
|
||||||
|
ARG MAIN_CLASS
|
||||||
|
ARG IMAGE_NAME
|
||||||
|
ARG IMAGE_TAG
|
||||||
|
|
||||||
|
ENV BUILD_FOLDER=${BUILD_FOLDER}
|
||||||
|
ENV MAIN_CLASS=${MAIN_CLASS}
|
||||||
|
ENV IMAGE_NAME=${IMAGE_NAME}
|
||||||
|
ENV IMAGE_TAG=${IMAGE_TAG}
|
||||||
|
|
||||||
|
# Log ARGs at build time
|
||||||
|
RUN echo "BUILD_FOLDER: ${BUILD_FOLDER}" && \
|
||||||
|
echo "MAIN_CLASS: ${MAIN_CLASS}" && \
|
||||||
|
echo "IMAGE_NAME: ${IMAGE_NAME}" && \
|
||||||
|
echo "IMAGE_TAG: ${IMAGE_TAG}"
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy artifacts (relative to /app)
|
||||||
|
COPY ${BUILD_FOLDER}/${IMAGE_NAME}-*.jar app.jar
|
||||||
|
COPY ${BUILD_FOLDER}/libs/ libs/
|
||||||
|
|
||||||
|
# Copy and set entrypoint (relative to /app)
|
||||||
|
COPY entrypoint.sh entrypoint.sh
|
||||||
|
RUN chmod +x entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["./entrypoint.sh"]
|
||||||
6
backend/Dockerfile.base
Normal file
6
backend/Dockerfile.base
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Dockerfile.base
|
||||||
|
FROM eclipse-temurin:21-jre
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY common/target/common-*.jar libs/common.jar
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>dev.rheinsw</groupId>
|
|
||||||
<artifactId>backend</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>discovery</artifactId>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<maven.compiler.source>21</maven.compiler.source>
|
|
||||||
<maven.compiler.target>21</maven.compiler.target>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</project>
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package dev.rheinsw.discovery;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Bummsa / BoomerHD / Thatsaphorn Atchariyaphap
|
|
||||||
* @since 21.04.25
|
|
||||||
*/
|
|
||||||
@SpringBootApplication
|
|
||||||
@EnableEurekaServer
|
|
||||||
public class DiscoveryServerApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(DiscoveryServerApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
server:
|
|
||||||
port: 8761
|
|
||||||
|
|
||||||
spring:
|
|
||||||
application:
|
|
||||||
name: discovery-server
|
|
||||||
|
|
||||||
eureka:
|
|
||||||
client:
|
|
||||||
register-with-eureka: false
|
|
||||||
fetch-registry: false
|
|
||||||
server:
|
|
||||||
wait-time-in-ms-when-sync-empty: 0
|
|
||||||
26
backend/entrypoint.sh
Normal file
26
backend/entrypoint.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "---------------------------"
|
||||||
|
echo "Starting Java Application"
|
||||||
|
echo "Main class : ${MAIN_CLASS}"
|
||||||
|
echo "App JAR : app.jar"
|
||||||
|
echo "Libs folder : libs/"
|
||||||
|
echo "Detected JARs in libs/:"
|
||||||
|
find libs -type f -name "*.jar" -exec echo " -> {}" \;
|
||||||
|
|
||||||
|
if [ ! -f app.jar ]; then
|
||||||
|
echo "ERROR: app.jar not found. Ensure it is copied into the container."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build classpath string
|
||||||
|
CLASSPATH="app.jar"
|
||||||
|
for jar in libs/*.jar; do
|
||||||
|
CLASSPATH="$CLASSPATH:$jar"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "---------------------------"
|
||||||
|
echo "Executing: java -cp \"$CLASSPATH\" $MAIN_CLASS"
|
||||||
|
echo "---------------------------"
|
||||||
|
|
||||||
|
exec java -cp "$CLASSPATH" "$MAIN_CLASS"
|
||||||
@@ -18,14 +18,55 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>${maven.compiler.plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${maven.compiler.source}</source>
|
||||||
|
<target>${maven.compiler.target}</target>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>3.6.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-dependencies</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
||||||
|
<includeScope>runtime</includeScope>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-gateway</artifactId>
|
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
<artifactId>caffeine</artifactId>
|
||||||
|
<version>3.2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Tools -->
|
<!-- Tools -->
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
server:
|
server:
|
||||||
port: 8080
|
port: 8080
|
||||||
|
|
||||||
eureka:
|
|
||||||
client:
|
|
||||||
service-url:
|
|
||||||
defaultZone: http://localhost:8761/eureka/
|
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: gateway
|
name: gateway
|
||||||
@@ -16,7 +11,7 @@ spring:
|
|||||||
gateway:
|
gateway:
|
||||||
routes:
|
routes:
|
||||||
- id: server
|
- id: server
|
||||||
uri: lb://server
|
uri: http://localhost:8081
|
||||||
predicates:
|
predicates:
|
||||||
- Path=/api/**
|
- Path=/api/**
|
||||||
filters:
|
filters:
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>common</module>
|
<module>common</module>
|
||||||
<module>discovery</module>
|
|
||||||
<module>gateway</module>
|
<module>gateway</module>
|
||||||
<module>server</module>
|
<module>server</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|||||||
@@ -36,6 +36,28 @@
|
|||||||
</annotationProcessorPaths>
|
</annotationProcessorPaths>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>3.6.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-dependencies</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
||||||
|
<includeScope>runtime</includeScope>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<!-- <plugin>-->
|
||||||
|
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||||
|
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||||
|
<!-- </plugin>-->
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
@@ -45,10 +67,6 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-mail</artifactId>
|
<artifactId>spring-boot-starter-mail</artifactId>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package dev.rheinsw.server.contact.controller;
|
package dev.rheinsw.server.contact.controller;
|
||||||
|
|
||||||
import dev.rheinsw.server.contact.domain.model.ContactRequestDto;
|
import dev.rheinsw.server.contact.model.ContactRequestDto;
|
||||||
import dev.rheinsw.server.contact.usecase.SubmitContactUseCase;
|
import dev.rheinsw.server.contact.usecase.SubmitContactUseCase;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.rheinsw.server.contact.domain.model;
|
package dev.rheinsw.server.contact.model;
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.rheinsw.server.contact.domain.model;
|
package dev.rheinsw.server.contact.model;
|
||||||
|
|
||||||
import dev.rheinsw.shared.transport.Dto;
|
import dev.rheinsw.shared.transport.Dto;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.rheinsw.server.contact.domain.model;
|
package dev.rheinsw.server.contact.model;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package dev.rheinsw.server.contact.repository;
|
package dev.rheinsw.server.contact.repository;
|
||||||
|
|
||||||
import dev.rheinsw.server.contact.domain.model.ContactRequest;
|
import dev.rheinsw.server.contact.model.ContactRequest;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package dev.rheinsw.server.contact.usecase;
|
package dev.rheinsw.server.contact.usecase;
|
||||||
|
|
||||||
import dev.rheinsw.server.contact.domain.model.ContactRequestDto;
|
import dev.rheinsw.server.contact.model.ContactRequestDto;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package dev.rheinsw.server.contact.usecase;
|
package dev.rheinsw.server.contact.usecase;
|
||||||
|
|
||||||
import dev.rheinsw.server.contact.domain.model.ContactRequest;
|
import dev.rheinsw.server.contact.model.ContactRequest;
|
||||||
import dev.rheinsw.server.contact.domain.model.ContactRequestDto;
|
import dev.rheinsw.server.contact.model.ContactRequestDto;
|
||||||
import dev.rheinsw.server.contact.repository.ContactRequestsRepo;
|
import dev.rheinsw.server.contact.repository.ContactRequestsRepo;
|
||||||
import dev.rheinsw.server.contact.util.HCaptchaValidator;
|
import dev.rheinsw.server.contact.util.HCaptchaValidator;
|
||||||
import dev.rheinsw.server.mail.domain.MailRequest;
|
import dev.rheinsw.server.mail.domain.MailRequest;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package dev.rheinsw.server.contact.util;
|
package dev.rheinsw.server.contact.util;
|
||||||
|
|
||||||
import dev.rheinsw.server.contact.domain.model.HCaptchaConfig;
|
import dev.rheinsw.server.contact.model.HCaptchaConfig;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
server:
|
server:
|
||||||
port: 0 # random port
|
port: 8081
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: server
|
name: server
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:postgresql://localhost:5432/rheinsw_dev
|
url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
|
||||||
username: rheinsw
|
username: ${DB_USERNAME}
|
||||||
password: rheinsw
|
password: ${DB_PASSWORD}
|
||||||
|
|
||||||
jpa:
|
jpa:
|
||||||
hibernate:
|
hibernate:
|
||||||
@@ -20,8 +20,8 @@ spring:
|
|||||||
mail:
|
mail:
|
||||||
host: smtp.resend.com
|
host: smtp.resend.com
|
||||||
port: 587
|
port: 587
|
||||||
username: resend
|
username: ${MAIL_USERNAME}
|
||||||
password: re_JnLD5ndg_GnKtXcTqskXm1bg7Wxnghna3
|
password: ${MAIL_PASSWORD}
|
||||||
properties:
|
properties:
|
||||||
mail:
|
mail:
|
||||||
smtp:
|
smtp:
|
||||||
@@ -30,15 +30,10 @@ spring:
|
|||||||
enable: true
|
enable: true
|
||||||
default-encoding: UTF-8
|
default-encoding: UTF-8
|
||||||
|
|
||||||
eureka:
|
|
||||||
client:
|
|
||||||
service-url:
|
|
||||||
defaultZone: http://localhost:8761/eureka/
|
|
||||||
|
|
||||||
hcaptcha:
|
hcaptcha:
|
||||||
secret: ES_ff59a664dc764f92870bf2c7b4eab7c5
|
secret: ${HCAPTCHA_SECRET}
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
org.hibernate.SQL: DEBUG
|
org.hibernate.SQL: ${LOG_SQL_LEVEL}
|
||||||
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
|
org.hibernate.type.descriptor.sql.BasicBinder: ${LOG_BINDER_LEVEL}
|
||||||
24
docker-compose.yml
Normal file
24
docker-compose.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
services:
|
||||||
|
gateway:
|
||||||
|
image: registry.boomlab.party/rheinsw/rheinsw-mono-repo/gateway
|
||||||
|
container_name: gateway
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
env_file:
|
||||||
|
- ./gateway.env
|
||||||
|
|
||||||
|
server:
|
||||||
|
image: registry.boomlab.party/rheinsw/rheinsw-mono-repo/server
|
||||||
|
container_name: server
|
||||||
|
ports:
|
||||||
|
- "8081:8081"
|
||||||
|
env_file:
|
||||||
|
- ./server.env
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
image: registry.boomlab.party/rheinsw/rheinsw-mono-repo/frontend
|
||||||
|
container_name: frontend
|
||||||
|
env_file:
|
||||||
|
- ./frontend.env
|
||||||
|
ports:
|
||||||
|
- "5100:3000"
|
||||||
@@ -1,35 +1,23 @@
|
|||||||
stages:
|
|
||||||
- frontend_build
|
|
||||||
- dockerize
|
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
key: ${CI_COMMIT_REF_SLUG}
|
key: ${CI_COMMIT_REF_SLUG}
|
||||||
paths:
|
paths:
|
||||||
- node_modules/
|
- node_modules/
|
||||||
- .next/cache/
|
- .next/cache/
|
||||||
|
|
||||||
variables:
|
build_frontend:
|
||||||
NEXT_PUBLIC_ENV: "production"
|
stage: build
|
||||||
OUTPUT_DIR: ".next"
|
|
||||||
PROJECT_NAME: $CI_PROJECT_NAME
|
|
||||||
DOCKER_IMAGE: $CI_REGISTRY_IMAGE
|
|
||||||
|
|
||||||
frontend_build_job:
|
|
||||||
stage: frontend_build
|
|
||||||
image: node:22@sha256:f6b9c31ace05502dd98ef777aaa20464362435dcc5e312b0e213121dcf7d8b95
|
image: node:22@sha256:f6b9c31ace05502dd98ef777aaa20464362435dcc5e312b0e213121dcf7d8b95
|
||||||
script:
|
script:
|
||||||
- cd frontend
|
- |
|
||||||
- npm install
|
cd frontend
|
||||||
- npx next build
|
npm install
|
||||||
- npm run lint
|
npx next build
|
||||||
|
|
||||||
dockerize_frontend:
|
docker_frontend:
|
||||||
stage: dockerize
|
extends: .docker-build-template
|
||||||
extends: .docker_build_template
|
|
||||||
variables:
|
variables:
|
||||||
DOCKER_CONTEXT: frontend
|
IMAGE_NAME: frontend
|
||||||
DOCKERFILE: Dockerfile
|
WORKDIR_PATH: frontend
|
||||||
DOCKER_IMAGE: $DOCKER_IMAGE
|
DOCKERFILE_PATH: Dockerfile
|
||||||
DOCKER_BUILD_ARGS: ""
|
|
||||||
needs:
|
needs:
|
||||||
- job: frontend_build_job
|
- build_frontend
|
||||||
|
|||||||
@@ -22,10 +22,7 @@ const ContactFormSection = () => {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
const isDev = process.env.NODE_ENV === "development";
|
const hCaptchaSiteKey: string = process.env.NEXT_PUBLIC_HCAPTCHA_SITE_KEY ?? "null";
|
||||||
const hCaptchaSiteKey = isDev
|
|
||||||
? "10000000-ffff-ffff-ffff-000000000001" // hCaptcha test sitekey
|
|
||||||
: "ES_ff59a664dc764f92870bf2c7b4eab7c5";
|
|
||||||
|
|
||||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||||
setForm({...form, [e.target.name]: e.target.value});
|
setForm({...form, [e.target.name]: e.target.value});
|
||||||
|
|||||||
Reference in New Issue
Block a user