Skip to content

Commit ff4d23b

Browse files
authored
Merge pull request #39 from prgrms-web-devcourse-final-project/develop
Chore[deploy]: 배포
2 parents ec0af4e + 2a57cef commit ff4d23b

File tree

63 files changed

+3432
-325
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+3432
-325
lines changed

.github/ISSUE_TEMPLATE/feature.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Feature
2+
description: 새로운 기능 개발을 위한 이슈 작성
3+
labels: [feat]
4+
body:
5+
- type: input
6+
id: title
7+
attributes:
8+
label: 기능 요약
9+
description: 어떤 기능을 추가하나요?
10+
placeholder: "예: 커뮤니티 게시판 작성 기능"
11+
validations:
12+
required: true
13+
14+
- type: textarea
15+
id: description
16+
attributes:
17+
label: 상세 설명
18+
description: 기능을 구체적으로 설명해주세요.
19+
placeholder: "어떤 문제를 해결하는지, 어떤 동작을 기대하는지"
20+
value: "/branch-name 기능명"
21+
validations:
22+
required: true
23+

.github/pull_request_template.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
## 📌 PR 제목
2-
- [Feat] 기능 추가
3-
- [Fix] 버그 수정
4-
- [Docs] 문서 수정
5-
- [Refactor] 리팩토링
6-
- [Chore] 기타 작업
2+
- Feat[기능을 써주세요]: 기능 추가
3+
- Fix[기능을 써주세요]: 버그 수정
4+
- Docs[기능을 써주세요]: 문서 수정
5+
- Refactor[기능을 써주세요]: 리팩토링
6+
- Chore[기능을 써주세요]: 기타 작업
77

88
## ✅ 작업 내용
99
- 어떤 작업을 했는지 간단히 설명해주세요.
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
name: CI-CD_Pipeline
2+
3+
permissions:
4+
contents: read
5+
packages: write
6+
id-token: write
7+
8+
on:
9+
push:
10+
branches: [ main, develop ]
11+
pull_request:
12+
branches: [ main, develop ]
13+
workflow_dispatch:
14+
15+
jobs:
16+
tests:
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
os: [ ubuntu-latest ]
21+
include:
22+
- os: ubuntu-latest
23+
gradle_cmd: "./gradlew"
24+
report_path: "backend/build/reports/tests"
25+
domain_tasks: "testUser testExchange testTrade_log testWallet testCoin"
26+
27+
runs-on: ${{ matrix.os }}
28+
env:
29+
SPRING_PROFILES_ACTIVE: test-ci
30+
31+
# ✅ Redis 서비스 추가
32+
services:
33+
redis:
34+
image: redis:7-alpine
35+
ports:
36+
- 6379:6379
37+
options: >-
38+
--health-cmd "redis-cli ping"
39+
--health-interval 10s
40+
--health-timeout 5s
41+
--health-retries 5
42+
env:
43+
REDIS_PASSWORD: ""
44+
45+
steps:
46+
- uses: actions/checkout@v4
47+
48+
- name: Set up JDK 21
49+
uses: actions/setup-java@v4
50+
with:
51+
java-version: '21'
52+
distribution: 'temurin'
53+
cache: gradle
54+
55+
# ✅ gradlew 실행 권한 부여
56+
- name: Grant execute permission for gradlew
57+
run: chmod +x backend/gradlew
58+
59+
# ✅ Redis 연결 테스트
60+
- name: Test Redis connection
61+
run: |
62+
echo "Testing Redis connection..."
63+
timeout 10s bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/localhost/6379; do sleep 1; done'
64+
echo "Redis is ready!"
65+
66+
# ✅ application-test.yml에서 사용하는 모든 환경변수를 .env 파일에 생성
67+
- name: Create test .env file
68+
working-directory: backend
69+
run: |
70+
cat > .env << 'EOF'
71+
# Datasource 설정 (application-test.yml에서 참조)
72+
TEST_DATASOURCE_URL=jdbc:h2:mem:db_test;MODE=MySQL
73+
TEST_DATASOURCE_USERNAME=sa
74+
TEST_DATASOURCE_PASSWORD=
75+
TEST_DATASOURCE_DRIVER=org.h2.Driver
76+
77+
# JPA 설정 (application-test.yml에서 참조)
78+
TEST_JPA_HIBERNATE_DDL_AUTO=create-drop
79+
80+
# Redis 설정 (application-test.yml에서 참조, GitHub Actions 서비스 사용)
81+
TEST_REDIS_HOST=localhost
82+
TEST_REDIS_PORT=6379
83+
TEST_REDIS_PASSWORD=
84+
85+
# CI/CD 환경에서는 Embedded Redis 끄기
86+
SPRING_DATA_REDIS_EMBEDDED=false
87+
88+
# JWT 설정 (application-test.yml에서 참조)
89+
CUSTOM_JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }}
90+
CUSTOM_JWT_ACCESS_TOKEN_EXPIRATION_SECONDS=3600
91+
EOF
92+
93+
- name: Run unit, and domain tests
94+
run: ${{ matrix.gradle_cmd }} clean test
95+
working-directory: backend
96+
97+
- name: Upload Test Reports
98+
if: always()
99+
uses: actions/upload-artifact@v4
100+
with:
101+
name: test-reports-${{ matrix.os }}
102+
path: ${{ matrix.report_path }}
103+
retention-days: 7
104+
105+
build-artifacts:
106+
needs: tests
107+
runs-on: ubuntu-latest
108+
if: github.ref == 'refs/heads/main' # ✅ main 브랜치일 때만 실행
109+
110+
steps:
111+
- uses: actions/checkout@v4
112+
113+
- uses: actions/setup-java@v4
114+
with:
115+
distribution: temurin
116+
java-version: 21
117+
cache: gradle
118+
119+
# ✅ gradlew 실행 권한 부여
120+
- name: Grant execute permission for gradlew
121+
run: chmod +x backend/gradlew
122+
123+
# ✅ 빌드용 .env 파일 생성 (Configuration Properties 바인딩용 최소 환경변수만)
124+
- name: Create build .env file
125+
working-directory: backend
126+
run: |
127+
cat > .env << 'EOF'
128+
# JWT Configuration Properties 바인딩용 (빌드 시 필요)
129+
CUSTOM_JWT_SECRET_KEY=build-dummy-key-for-configuration-properties-binding
130+
CUSTOM_JWT_ACCESS_TOKEN_EXPIRATION_SECONDS=3600
131+
EOF
132+
133+
- name: Gradle bootJar
134+
working-directory: backend
135+
run: ./gradlew --no-daemon clean bootJar -x test
136+
137+
- name: Copy JAR to dist
138+
working-directory: backend
139+
run: |
140+
mkdir -p dist
141+
cp $(ls build/libs/*.jar | grep -v plain | head -n 1) dist/app.jar
142+
143+
- name: Upload backend jar
144+
uses: actions/upload-artifact@v4
145+
with:
146+
name: backend-jar
147+
path: backend/dist/app.jar
148+
149+
docker-build:
150+
needs: build-artifacts
151+
runs-on: ubuntu-latest
152+
if: github.ref == 'refs/heads/main' # ✅ main 브랜치일 때만 실행
153+
env:
154+
REGISTRY: ghcr.io
155+
IMAGE_PREFIX: ${{ github.repository_owner }}
156+
157+
steps:
158+
- uses: actions/checkout@v4
159+
160+
- name: Download backend jar
161+
uses: actions/download-artifact@v4
162+
with:
163+
name: backend-jar
164+
path: backend/dist
165+
166+
- uses: docker/setup-buildx-action@v3
167+
168+
- uses: docker/login-action@v3
169+
with:
170+
registry: ${{ env.REGISTRY }}
171+
username: ${{ github.actor }}
172+
password: ${{ secrets.GITHUB_TOKEN }}
173+
174+
- name: Build & push backend (runtime-only)
175+
uses: docker/build-push-action@v6
176+
with:
177+
context: backend
178+
file: backend/Dockerfile
179+
push: true
180+
tags: |
181+
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/backend:${{ github.sha }}
182+
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/backend:latest
183+
cache-from: type=gha
184+
cache-to: type=gha,mode=max
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Create branch from issue
2+
on:
3+
issues:
4+
types: [opened, labeled] # 이슈 생성 또는 라벨 붙을 때 작동
5+
6+
jobs:
7+
create-branch:
8+
runs-on: ubuntu-latest
9+
permissions:
10+
contents: write
11+
steps:
12+
- name: Checkout repository
13+
uses: actions/checkout@v4
14+
15+
- name: Decide branch prefix
16+
id: prefix
17+
run: |
18+
PREFIX="feat" # 기본값
19+
for label in ${{ join(github.event.issue.labels.*.name, ' ') }}; do
20+
if [[ "$label" =~ ^(feat|bug|refactor|chore)$ ]]; then
21+
PREFIX=$label
22+
break
23+
fi
24+
done
25+
echo "prefix=$PREFIX" >> $GITHUB_OUTPUT
26+
27+
- name: Get custom branch name from issue body
28+
id: custom
29+
run: |
30+
CUSTOM=$(echo "${{ github.event.issue.body }}" | grep -oP '(?<=/branch-name ).*' || true)
31+
if [ -n "$CUSTOM" ]; then
32+
echo "custom_name=$CUSTOM" >> $GITHUB_OUTPUT
33+
else
34+
echo "custom_name=" >> $GITHUB_OUTPUT
35+
fi
36+
37+
- name: Create branch
38+
run: |
39+
ISSUE_NUMBER=${{ github.event.issue.number }}
40+
ISSUE_TITLE="${{ github.event.issue.title }}"
41+
42+
# 영어/숫자만 남기고, 나머지는 - 로 치환
43+
SANITIZED_TITLE=$(echo "$ISSUE_TITLE" | iconv -t ascii//translit | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-')
44+
45+
if [ -n "${{ steps.custom.outputs.custom_name }}" ]; then
46+
RAW_NAME="${{ steps.custom.outputs.custom_name }}"
47+
# 앞뒤 공백 제거
48+
CUSTOM_NAME=$(echo "$RAW_NAME" | xargs)
49+
BRANCH_NAME="${{ steps.prefix.outputs.prefix }}/${ISSUE_NUMBER}-${CUSTOM_NAME}"
50+
else
51+
BRANCH_NAME="${{ steps.prefix.outputs.prefix }}/${ISSUE_NUMBER}-${SANITIZED_TITLE}"
52+
fi
53+
54+
echo "Creating branch: $BRANCH_NAME"
55+
56+
git config user.name "github-actions[bot]"
57+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
58+
59+
DEFAULT_BRANCH=${{ github.event.repository.default_branch }}
60+
git fetch origin $DEFAULT_BRANCH
61+
git checkout -b "$BRANCH_NAME" origin/$DEFAULT_BRANCH
62+
git push origin "$BRANCH_NAME"

.github/workflows/deploy.yml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: deploy
2+
on:
3+
push:
4+
paths:
5+
- '.github/workflows/**'
6+
- 'src/**'
7+
- 'build.gradle.kts'
8+
- 'settings.gradle.kts'
9+
- 'Dockerfile'
10+
branches:
11+
- main
12+
jobs:
13+
makeTagAndRelease:
14+
runs-on: ubuntu-latest
15+
outputs:
16+
tag_name: ${{ steps.create_tag.outputs.new_tag }}
17+
steps:
18+
- uses: actions/checkout@v4
19+
- name: Create Tag
20+
id: create_tag
21+
uses: mathieudutour/[email protected]
22+
with:
23+
github_token: ${{ secrets.GITHUB_TOKEN }}
24+
- name: Create Release
25+
id: create_release
26+
uses: actions/create-release@v1
27+
env:
28+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
with:
30+
tag_name: ${{ steps.create_tag.outputs.new_tag }}
31+
release_name: Release ${{ steps.create_tag.outputs.new_tag }}
32+
body: ${{ steps.create_tag.outputs.changelog }}
33+
draft: false
34+
prerelease: false
35+
buildImageAndPush:
36+
name: 도커 이미지 빌드와 푸시
37+
needs: makeTagAndRelease
38+
runs-on: ubuntu-latest
39+
env:
40+
DOCKER_IMAGE_NAME: balaw
41+
outputs:
42+
DOCKER_IMAGE_NAME: ${{ env.DOCKER_IMAGE_NAME }}
43+
steps:
44+
- uses: actions/checkout@v4
45+
- name: application-secret.yml 생성
46+
env:
47+
APPLICATION_SECRET: ${{ secrets.APPLICATION_SECRET_YML }}
48+
run: echo "$APPLICATION_SECRET" > src/main/resources/application-secret.yml
49+
- name: Docker Buildx 설치
50+
uses: docker/setup-buildx-action@v2
51+
- name: 레지스트리 로그인
52+
uses: docker/login-action@v2
53+
with:
54+
registry: ghcr.io
55+
username: ${{ github.actor }}
56+
password: ${{ secrets.GITHUB_TOKEN }}
57+
- name: set lower case owner name
58+
run: |
59+
echo "OWNER_LC=${OWNER,,}" >> ${GITHUB_ENV}
60+
env:
61+
OWNER: '${{ github.repository_owner }}'
62+
- name: 빌드 앤 푸시
63+
uses: docker/build-push-action@v3
64+
with:
65+
context: .
66+
push: true
67+
tags: |
68+
ghcr.io/${{ env.OWNER_LC }}/${{ env.DOCKER_IMAGE_NAME }}:${{ needs.makeTagAndRelease.outputs.tag_name }},
69+
ghcr.io/${{ env.OWNER_LC }}/${{ env.DOCKER_IMAGE_NAME }}:latest
70+
71+
deploy:
72+
runs-on: ubuntu-latest
73+
needs: [ buildImageAndPush ]
74+
env:
75+
DOCKER_IMAGE_NAME: ${{ needs.buildImageAndPush.outputs.DOCKER_IMAGE_NAME }}
76+
steps:
77+
- name: AWS SSM Send-Command
78+
uses: peterkimzz/aws-ssm-send-command@master
79+
id: ssm
80+
with:
81+
aws-region: ${{ secrets.AWS_REGION }}
82+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
83+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
84+
instance-ids: "i-0b903187bca01a1c4"
85+
working-directory: /
86+
comment: Deploy
87+
command: |
88+
docker pull ghcr.io/doohyojeong/${{ env.DOCKER_IMAGE_NAME }}:latest
89+
docker stop app1 2>/dev/null
90+
docker rm app1 2>/dev/null
91+
docker run -d --name app1 -p 8080:8080 ghcr.io/doohyojeong/${{ env.DOCKER_IMAGE_NAME }}:latest
92+
docker rmi $(docker images -f "dangling=true" -q)

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.idea
2+
db_dev.mv.db

0 commit comments

Comments
 (0)