17 Commits

Author SHA1 Message Date
revlis44
745c5a7461 harbor로그인 시 비밀번호 특수문자가 있으면 printf %s 사용해야함
All checks were successful
PR-CI / build-test (pull_request) Successful in 17s
2025-12-09 13:30:51 +09:00
revlis44
a586ba28bd harbor 2025-12-09 12:11:34 +09:00
revlis44
7b47a02d9a ddd
All checks were successful
PR-CI / build-test (pull_request) Successful in 33s
2025-12-09 12:09:19 +09:00
revlis44
7fb2bfdfa4 dd 2025-12-09 12:06:34 +09:00
revlis44
98a8159d9f d 2025-12-09 12:05:22 +09:00
632eaa721e favicon 강제 캐쉬
Some checks failed
Main-Build / build-and-push (push) Failing after 17s
2025-12-09 11:58:08 +09:00
b6ab357703 favicon 강제 캐쉬
Some checks failed
Main-Build / build-and-push (push) Failing after 16s
2025-12-09 11:49:01 +09:00
8fca06fcbc favicon 강제 캐쉬
Some checks failed
Main-Build / build-and-push (push) Failing after 15s
2025-12-09 11:43:21 +09:00
53887b77ed Merge pull request '파비콘 추가' (#14) from feature/favicon into master
Some checks failed
Main-Build / build-and-push (push) Failing after 16s
Reviewed-on: #14
Reviewed-by: saydev <gomdobi@sayinfo.co.kr>
2025-12-09 02:07:25 +00:00
revlis44
2808bbc29d 파비콘 추가
Some checks failed
PR-CI / build-test (pull_request) Failing after 4m55s
2025-12-09 11:06:54 +09:00
fc1420a0ea Merge pull request 'favicon 변경' (#13) from feature/favicon into master
Some checks failed
Main-Build / build-and-push (push) Failing after 28s
Reviewed-on: #13
Reviewed-by: saydev <gomdobi@sayinfo.co.kr>
2025-12-09 01:55:45 +00:00
80b13f2893 JVM 옵션 정리
Some checks failed
Main-Build / build-and-push (push) Has been cancelled
2025-12-09 10:43:50 +09:00
revlis44
ea2ecf2539 favicon 변경
Some checks failed
PR-CI / build-test (pull_request) Failing after 6m30s
2025-12-09 10:29:00 +09:00
75b5328f27 무중단 배포용 Jenkinsfile 생성
Some checks failed
Main-Build / build-and-push (push) Has been cancelled
2025-12-09 09:39:26 +09:00
320e64f929 무중단 배포용 /health 200 응답 기능 Spring Security 예외 처리 추가 (login session 제외)
Some checks failed
Main-Build / build-and-push (push) Failing after 17s
2025-12-08 17:05:20 +09:00
58d246a993 무중단 배포용 /health 200 응답 기능 Spring Security 예외 처리 추가
Some checks failed
Main-Build / build-and-push (push) Failing after 22s
2025-12-08 16:24:34 +09:00
9eade14238 무중단 배포용 /health 200 응답 기능 Spring Security 예외 처리 추가
Some checks failed
Main-Build / build-and-push (push) Failing after 4s
2025-12-08 16:17:39 +09:00
16 changed files with 54 additions and 80 deletions

View File

@@ -2,55 +2,30 @@ name: Main-Build
on: on:
push: push:
branches: ["master"] branches: ["master"]
jobs: jobs:
build-and-push: build-and-push:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container:
image: ci-maven-node:1.0
steps: steps:
- name: Checkout - uses: actions/checkout@v4
uses: actions/checkout@v4
- name: Set up JDK 8
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "8"
- name: Maven Build WAR - name: Maven Build WAR
run: mvn -B clean package -DskipTests run: mvn -B clean package -DskipTests
# ------------------------------ - name: Login Harbor
# 🔻 Harbor 관련 기능 임시 비활성화
# ------------------------------
# - name: Docker login to Harbor
# run: |
# echo "${{ secrets.HARBOR_PASSWORD }}" | docker login harbor.sayinfo.co.kr -u ${{ secrets.HARBOR_USERNAME }} --password-stdin
# - name: Build Docker image
# run: |
# docker build -t sayit-helpdesk:latest .
# - name: Tag image for Harbor
# run: |
# docker tag sayit-helpdesk:latest harbor.sayinfo.co.kr/helpdesk/helpdesk-service:latest
# - name: Push image to Harbor
# run: |
# docker push harbor.sayinfo.co.kr/helpdesk/helpdesk-service:latest
# ------------------------------
# 끝 (Harbor 비활성화)
# ------------------------------
- name: Build Docker image (local only, no push)
run: | run: |
docker build -t sayit-helpdesk:local-test . printf "%s" "$HARBOR_PASSWORD" | docker login harbor.sayinfo.co.kr -u "$HARBOR_USERNAME" --password-stdin
env:
HARBOR_USERNAME: ${{ secrets.HARBOR_USERNAME }}
HARBOR_PASSWORD: ${{ secrets.HARBOR_PASSWORD }}
- name: Done - name: Build Docker image
run: echo "Main branch build completed (Harbor push disabled)." run: |
docker build -t sayit-helpdesk:latest .
- name: Push to Harbor
run: |
docker tag sayit-helpdesk:latest harbor.sayinfo.co.kr/sayit-helpdesk-gitea_action_runner_test/helpdesk-service:latest
docker push harbor.sayinfo.co.kr/sayit-helpdesk-gitea_action_runner_test/helpdesk-service:latest

View File

@@ -2,33 +2,15 @@ name: PR-CI
on: on:
pull_request: pull_request:
types: [opened, synchronize] # PR 생성 + 커밋 push 때만 실행 types: [opened, synchronize]
branches: ["master"] branches: ["master"]
jobs: jobs:
build-test: build-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container:
image: ci-maven-node:1.0
steps: steps:
- name: Checkout source - uses: actions/checkout@v4
uses: actions/checkout@v4
- name: Set up JDK 8 - name: Maven Build (skip tests)
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "8"
- name: Cache Maven repo
uses: actions/cache@v4
with:
path: ~/.m2
key: m2-${{ runner.os }}-${{ hashFiles('**/pom.xml') }}
restore-keys: |
m2-${{ runner.os }}-
- name: Maven Build (compile + dependency check)
run: mvn -B clean package -DskipTests run: mvn -B clean package -DskipTests

View File

@@ -7,7 +7,7 @@ RUN apk add --no-cache curl && \
https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${OTEL_VERSION}/opentelemetry-javaagent.jar \ https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${OTEL_VERSION}/opentelemetry-javaagent.jar \
-o /opentelemetry-javaagent.jar -o /opentelemetry-javaagent.jar
# 2단계: Tomcat 이미지 (Java 8 기준, Java 17 쓸 거면 jdk17-temurin 그대로 사용) # 2단계: Tomcat 이미지 (Java 8 기준)
FROM tomcat:9.0-jdk8-temurin FROM tomcat:9.0-jdk8-temurin
ENV TZ=Asia/Seoul \ ENV TZ=Asia/Seoul \
@@ -15,23 +15,30 @@ ENV TZ=Asia/Seoul \
OTEL_EXPORTER_OTLP_ENDPOINT=http://192.168.100.203:4317 \ OTEL_EXPORTER_OTLP_ENDPOINT=http://192.168.100.203:4317 \
OTEL_EXPORTER_OTLP_PROTOCOL=grpc \ OTEL_EXPORTER_OTLP_PROTOCOL=grpc \
OTEL_RESOURCE_ATTRIBUTES="deployment.environment=prod" \ OTEL_RESOURCE_ATTRIBUTES="deployment.environment=prod" \
JAVA_TOOL_OPTIONS="-javaagent:/opt/opentelemetry-javaagent.jar" JAVA_TOOL_OPTIONS="\
-Xms1g \
-Xmx1g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:+UnlockExperimentalVMOptions \
-XX:+UseStringDeduplication \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/tmp \
-XX:+DisableExplicitGC \
-javaagent:/opt/opentelemetry-javaagent.jar"
# 타임존 설정 # 타임존 설정
RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
# OTEL 에이전트 복사 # OTEL 에이전트 복사
COPY --from=otel /opentelemetry-javaagent.jar /opt/opentelemetry-javaagent.jar COPY --from=otel /opentelemetry-javaagent.jar /opt/opentelemetry-javaagent.jar
# OTEL 1000:1000 으로 구동 가능 하도록 처리
RUN chown 1000:1000 /opt/opentelemetry-javaagent.jar RUN chown 1000:1000 /opt/opentelemetry-javaagent.jar
# 🔽 기본 웹앱 정리 # 기본 웹앱 정리
RUN rm -rf /usr/local/tomcat/webapps/* RUN rm -rf /usr/local/tomcat/webapps/*
# Maven 빌드된 WAR 복사 # Maven 빌드된 WAR 복사
# Maven 빌드 결과 파일명에 맞게 수정
COPY target/sayit-helpdesk.war /usr/local/tomcat/webapps/ROOT.war COPY target/sayit-helpdesk.war /usr/local/tomcat/webapps/ROOT.war
# TOMCAT 구동전 톰캣은 1000:1000 으로 구동 할 수 있도록 조정
RUN chown -R 1000:1000 /usr/local/tomcat/ RUN chown -R 1000:1000 /usr/local/tomcat/
EXPOSE 8080 EXPOSE 8080

20
Jenkinsfile vendored
View File

@@ -1,9 +1,10 @@
// Jenkinsfile — Kaniko build + K8s deploy (latest only) // Jenkinsfile — Kaniko build + K8s deploy (빌드번호 태그 사용)
def L = 'kaniko-and-deploy' def L = 'kaniko-and-deploy'
def REG = 'harbor.sayinfo.co.kr' def REG = 'harbor.sayinfo.co.kr'
def IMAGE = 'sayit-helpdesk/helpdesk-service' // Harbor 프로젝트/레포 이름에 맞게 유지 또는 수정 def IMAGE = 'sayit-helpdesk/helpdesk-service' // Harbor 프로젝트/레포 이름
def APP_NS = 'sayit-helpdesk' // 실제 K8s 네임스페이스와 일치해야 함 def APP_NS = 'sayit-helpdesk' // 실제 K8s 네임스페이스
def DEPLOY = 'sayit-helpdesk-service' // 실제 Deployment 이름과 일치해야 함 def DEPLOY = 'sayit-helpdesk-service' // 실제 Deployment 이름
def IMAGE_TAG = "${env.BUILD_NUMBER}"
podTemplate( podTemplate(
label: L, label: L,
@@ -104,7 +105,7 @@ spec:
/kaniko/executor \\ /kaniko/executor \\
--context=. \\ --context=. \\
--dockerfile=Dockerfile \\ --dockerfile=Dockerfile \\
--destination=${REG}/${IMAGE}:latest \\ --destination=${REG}/${IMAGE}:${IMAGE_TAG} \\
--snapshot-mode=redo \\ --snapshot-mode=redo \\
--skip-tls-verify \\ --skip-tls-verify \\
--cache=true \\ --cache=true \\
@@ -113,12 +114,11 @@ spec:
} }
} }
stage('Deploy to Kubernetes') { stage('Deploy to Kubernetes') {
container('kubectl') { container('kubectl') {
sh """ sh """
set -eux set -eux
kubectl -n ${APP_NS} set image deploy/${DEPLOY} ${DEPLOY}=${REG}/${IMAGE}:latest kubectl -n ${APP_NS} set image deploy/${DEPLOY} ${DEPLOY}=${REG}/${IMAGE}:${IMAGE_TAG}
kubectl -n ${APP_NS} rollout restart deploy/${DEPLOY}
kubectl -n ${APP_NS} rollout status deploy/${DEPLOY} --timeout=300s kubectl -n ${APP_NS} rollout status deploy/${DEPLOY} --timeout=300s
kubectl -n ${APP_NS} get deploy ${DEPLOY} -o wide kubectl -n ${APP_NS} get deploy ${DEPLOY} -o wide

View File

@@ -45,7 +45,9 @@ public class AuthenticInterceptor extends HandlerInterceptorAdapter {
uri.equals("/") || uri.equals("/") ||
uri.equals("/actionLoginSys.do") || uri.equals("/actionLoginSys.do") ||
uri.equals("/js/") || uri.equals("/js/") ||
uri.equals("/images/") uri.equals("/images/") ||
uri.equals("/health.do")
) { ) {
return true; return true;
} }

View File

@@ -91,7 +91,7 @@ public class MainController {
return startPage; return startPage;
} }
@RequestMapping(value = "/health", method = RequestMethod.GET) @RequestMapping(value = "/health.do", method = RequestMethod.GET)
public void health(HttpServletResponse response) throws IOException { public void health(HttpServletResponse response) throws IOException {
response.setStatus(HttpServletResponse.SC_OK); response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("text/plain;charset=UTF-8"); response.setContentType("text/plain;charset=UTF-8");

View File

@@ -20,6 +20,7 @@
<security:http pattern="/js/**" security="none"/> <security:http pattern="/js/**" security="none"/>
<security:http pattern="/resource/**" security="none"/> <security:http pattern="/resource/**" security="none"/>
<security:http pattern="\A/WEB-INF/jsp/.*\Z" request-matcher="regex" security="none"/> <security:http pattern="\A/WEB-INF/jsp/.*\Z" request-matcher="regex" security="none"/>
<security:http pattern="/health.do" security="none"/>
<egov-security:config id="securityConfig" <egov-security:config id="securityConfig"
loginUrl="/login.do" loginUrl="/login.do"

BIN
src/main/webapp/Favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -17,6 +17,7 @@
<script src="js/common/login.js"></script> <script src="js/common/login.js"></script>
<base target="_self" /> <base target="_self" />
<title><%=MainGlobals.SITE_TITLE%></title> <title><%=MainGlobals.SITE_TITLE%></title>
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
<style> <style>
.login_wrap_body{ background:url(${pageContext.request.contextPath}/images/admin/login_bg.gif) repeat left top; font-family:"맑은 고딕",Malgun Gothic,AppleGothic,sans-serif,"돋움", Dotum; } .login_wrap_body{ background:url(${pageContext.request.contextPath}/images/admin/login_bg.gif) repeat left top; font-family:"맑은 고딕",Malgun Gothic,AppleGothic,sans-serif,"돋움", Dotum; }
.login_wrap{display:block; height:100%; left:0; position:fixed; top:0; width:100%; z-index:10000;} .login_wrap{display:block; height:100%; left:0; position:fixed; top:0; width:100%; z-index:10000;}

View File

@@ -12,6 +12,7 @@
<meta name="keywords" content="" /> <meta name="keywords" content="" />
<base target="_self" /> <base target="_self" />
<title><%=MainGlobals.SITE_TITLE%></title> <title><%=MainGlobals.SITE_TITLE%></title>
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script> <script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>

View File

@@ -22,6 +22,7 @@ if(UserHelper.isAuthenticated()) {
<meta name="keywords" content="" /> <meta name="keywords" content="" />
<base target="_self" /> <base target="_self" />
<title><%=MainGlobals.SITE_TITLE%></title> <title><%=MainGlobals.SITE_TITLE%></title>
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script> <script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>

View File

@@ -23,6 +23,7 @@ if(UserHelper.isAuthenticated()) {
<meta name="keywords" content="" /> <meta name="keywords" content="" />
<base target="_self" /> <base target="_self" />
<title><%=MainGlobals.SITE_TITLE%></title> <title><%=MainGlobals.SITE_TITLE%></title>
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script> <script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>

View File

@@ -22,6 +22,7 @@ if(UserHelper.isAuthenticated()) {
<meta name="keywords" content="" /> <meta name="keywords" content="" />
<base target="_self" /> <base target="_self" />
<title><%=MainGlobals.SITE_TITLE%></title> <title><%=MainGlobals.SITE_TITLE%></title>
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script> <script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>

View File

@@ -13,6 +13,7 @@
<meta name="keywords" content="noframe" /> <meta name="keywords" content="noframe" />
<base target="_self" /> <base target="_self" />
<title><%=MainGlobals.SITE_TITLE%></title> <title><%=MainGlobals.SITE_TITLE%></title>
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
<script type="text/javascript">var G_CONTEXT_PATH = "${pageContext.request.contextPath}";</script> <script type="text/javascript">var G_CONTEXT_PATH = "${pageContext.request.contextPath}";</script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>

View File

@@ -22,6 +22,7 @@ if(UserHelper.isAuthenticated()) {
<meta name="keywords" content="" /> <meta name="keywords" content="" />
<base target="_self" /> <base target="_self" />
<title><%=MainGlobals.SITE_TITLE%></title> <title><%=MainGlobals.SITE_TITLE%></title>
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script> <script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB