Skip to content

Commit 9f65844

Browse files
authored
infra: 배포 자동화 스크립트 작성 (#192)
1 parent 582105b commit 9f65844

File tree

17 files changed

+600
-6
lines changed

17 files changed

+600
-6
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
name: yappu-world-oci-dev-cd
2+
3+
on:
4+
push:
5+
branches:
6+
- dev
7+
- infra/oci-cd
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up JDK 21
18+
uses: actions/setup-java@v4
19+
with:
20+
java-version: '21'
21+
distribution: 'liberica'
22+
cache: gradle
23+
24+
- name: Setup Gradle
25+
uses: gradle/actions/setup-gradle@v3
26+
27+
- name: Copy Secrets
28+
uses: microsoft/variable-substitution@v1
29+
with:
30+
files:
31+
./src/main/resources/application-dev-oci.yaml
32+
env:
33+
server.port: ${{ secrets.DEV_SERVER_PORT }}
34+
spring.datasource.url: ${{ secrets.DEV_OCI_DB_URL }}
35+
spring.datasource.username: ${{ secrets.DEV_OCI_DB_USERNAME }}
36+
spring.datasource.password: ${{ secrets.DEV_OCI_DB_PASSWORD }}
37+
jwt.secret_key: ${{ secrets.DEV_JWT_SECRET_KEY }}
38+
jwt.access_token_expiration_times: ${{ secrets.DEV_ACCESS_TOKEN_EXPIRATION_TIMES }}
39+
jwt.refresh_token_expiration_times: ${{ secrets.DEV_REFRESH_TOKEN_EXPIRATION_TIMES }}
40+
fcm.private_key_id: ${{secrets.FCM_PRIVATE_KEY_ID}}
41+
fcm.private_key: ${{secrets.FCM_PRIVATE_KEY}}
42+
fcm.client_email: ${{secrets.FCM_CLIENT_EMAIL}}
43+
fcm.client_id: ${{secrets.FCM_CLIENT_ID}}
44+
fcm.client_x509_cert_url: ${{secrets.FCM_X509_CERT_URL}}
45+
discord.webhook: ${{secrets.DISCORD_WEBHOOK_URL_IN_DEV}}
46+
sentry.dsn: ${{secrets.SENTRY_DSN}}
47+
admin.domain: ${{ secrets.DEV_ADMIN_DOMAIN }}
48+
kakao.rest_api_key: ${{ secrets.KAKAO_REST_API_KEY }}
49+
50+
- name: Build with Gradle Wrapper
51+
run: ./gradlew clean build -x test -Dspring.profiles.active=dev-oci
52+
53+
- name: Prepare File for Deployment
54+
run: |
55+
mkdir -p deployment/dev/build/libs
56+
cp ./docker/dockerfile-dev-oci ./docker/docker-compose-dev-oci.yaml deployment/dev/
57+
cp -r ./build/libs/yappu-world-dev-oci.jar deployment/dev/build/libs
58+
59+
# Github Action 실행 서버 IP 추출
60+
- name: Get Github Actions IP
61+
id: ip
62+
uses: candidob/[email protected]
63+
64+
# OCI CLI 설정
65+
- name: Setup OCI CLI
66+
run: |
67+
mkdir -p ~/.oci
68+
echo "${{ secrets.OCI_CLI_KEY_CONTENT }}" > ~/.oci/key.pem
69+
chmod 600 ~/.oci/key.pem
70+
71+
cat > ~/.oci/config << EOF
72+
[DEFAULT]
73+
user=${{ secrets.OCI_CLI_USER }}
74+
fingerprint=${{ secrets.OCI_CLI_FINGERPRINT }}
75+
tenancy=${{ secrets.OCI_CLI_TENANCY }}
76+
region=${{ secrets.OCI_CLI_REGION }}
77+
key_file=~/.oci/key.pem
78+
EOF
79+
80+
chmod 600 ~/.oci/config
81+
82+
# OCI CLI 설치
83+
curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh | bash -s -- --accept-all-defaults
84+
echo "$HOME/bin" >> $GITHUB_PATH
85+
~/bin/oci --version
86+
87+
# NSG에 Github Action 서버를 등록
88+
- name: Add Github Actions IP to OCI NSG
89+
run: |
90+
~/bin/oci network nsg rules add \
91+
--nsg-id ${{ secrets.OCI_DEV_NSG_OCID }} \
92+
--security-rules '[{
93+
"direction": "INGRESS",
94+
"protocol": "6",
95+
"source": "${{ steps.ip.outputs.ipv4 }}/32",
96+
"sourceType": "CIDR_BLOCK",
97+
"tcpOptions": {
98+
"destinationPortRange": {
99+
"min": 22,
100+
"max": 22
101+
}
102+
},
103+
"description": "GitHub Actions temporary access",
104+
"isStateless": false
105+
}]'
106+
107+
- name: Wait for NSG rule to propagate
108+
run: sleep 10
109+
110+
- name: Setup SSH Key
111+
run: |
112+
mkdir -p ~/.ssh
113+
echo "${{ secrets.OCI_DEV_SSH_PRIVATE_KEY }}" > ~/.ssh/oci_dev_key
114+
chmod 600 ~/.ssh/oci_dev_key
115+
116+
- name: Upload files to OCI Instance
117+
uses: appleboy/[email protected]
118+
with:
119+
host: ${{ secrets.OCI_DEV_INSTANCE_IP }}
120+
username: ubuntu
121+
key: ${{ secrets.OCI_DEV_SSH_PRIVATE_KEY }}
122+
source: "deployment/dev/*"
123+
target: "/home/ubuntu"
124+
125+
- name: Deploy using Docker Compose
126+
uses: appleboy/[email protected]
127+
with:
128+
host: ${{ secrets.OCI_DEV_INSTANCE_IP }}
129+
username: ubuntu
130+
key: ${{ secrets.OCI_DEV_SSH_PRIVATE_KEY }}
131+
script: |
132+
cd /home/ubuntu/deployment/dev
133+
docker-compose -f docker-compose-dev-oci.yaml down
134+
docker system prune -f
135+
docker-compose -f docker-compose-dev-oci.yaml build --no-cache
136+
docker-compose -f docker-compose-dev-oci.yaml up -d
137+
138+
- name: Remove Github Actions IP from OCI NSG
139+
if: always()
140+
run: |
141+
# NSG 규칙 ID 찾기
142+
RULE_ID=$(~/bin/oci network nsg rules list \
143+
--nsg-id ${{ secrets.OCI_DEV_NSG_OCID }} \
144+
--all \
145+
--query "data[?source=='${{ steps.ip.outputs.ipv4 }}/32' && direction=='INGRESS'].id | [0]" \
146+
--raw-output)
147+
148+
if [ ! -z "$RULE_ID" ] && [ "$RULE_ID" != "null" ]; then
149+
~/bin/oci network nsg rules remove \
150+
--nsg-id ${{ secrets.OCI_DEV_NSG_OCID }} \
151+
--security-rule-ids "[\"$RULE_ID\"]"
152+
fi
153+
154+
- name: Cleanup
155+
if: always()
156+
run: |
157+
rm -f ~/.oci/key.pem
158+
rm -f ~/.ssh/oci_dev_key
159+
160+
# Discord Notification
161+
- name: CD Success Notification
162+
uses: sarisia/actions-status-discord@v1
163+
if: success()
164+
with:
165+
title: ✅ OCI 개발 환경 배포 성공 ✅
166+
webhook: ${{ secrets.DISCORD_WEBHOOK_URL }}
167+
color: 0x00FF00
168+
username: 페페훅
169+
170+
- name: CD Failure Notification
171+
uses: sarisia/actions-status-discord@v1
172+
if: failure()
173+
with:
174+
title: ❗️OCI 개발 환경 배포 실패 ❗️
175+
webhook: ${{ secrets.DISCORD_WEBHOOK_URL }}
176+
color: 0xFF0000
177+
username: 페페훅
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
name: yappu-world-oci-prod-cd
2+
3+
on:
4+
push:
5+
branches:
6+
- prod
7+
- infra/oci-cd
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up JDK 21
18+
uses: actions/setup-java@v4
19+
with:
20+
java-version: '21'
21+
distribution: 'liberica'
22+
cache: gradle
23+
24+
- name: Setup Gradle
25+
uses: gradle/actions/setup-gradle@v3
26+
27+
- name: Copy Secrets
28+
uses: microsoft/variable-substitution@v1
29+
with:
30+
files:
31+
./src/main/resources/application-prod-oci.yaml
32+
env:
33+
spring.datasource.url: ${{ secrets.PROD_OCI_DB_URL }}
34+
spring.datasource.username: ${{ secrets.PROD_OCI_DB_USERNAME }}
35+
spring.datasource.password: ${{ secrets.PROD_OCI_DB_PASSWORD }}
36+
jwt.secret_key: ${{ secrets.PROD_JWT_SECRET_KEY }}
37+
jwt.access_token_expiration_times: ${{ secrets.PROD_ACCESS_TOKEN_EXPIRATION_TIMES }}
38+
jwt.refresh_token_expiration_times: ${{ secrets.PROD_REFRESH_TOKEN_EXPIRATION_TIMES }}
39+
fcm.private_key_id: ${{secrets.FCM_PRIVATE_KEY_ID}}
40+
fcm.private_key: ${{secrets.FCM_PRIVATE_KEY}}
41+
fcm.client_email: ${{secrets.FCM_CLIENT_EMAIL}}
42+
fcm.client_id: ${{secrets.FCM_CLIENT_ID}}
43+
fcm.client_x509_cert_url: ${{secrets.FCM_X509_CERT_URL}}
44+
discord.webhook: ${{secrets.DISCORD_WEBHOOK_URL_IN_PROD}}
45+
sentry.dsn: ${{secrets.SENTRY_DSN}}
46+
admin.domain: ${{ secrets.PROD_ADMIN_DOMAIN }}
47+
kakao.rest_api_key: ${{ secrets.KAKAO_REST_API_KEY }}
48+
49+
- name: Build with Gradle Wrapper
50+
run: ./gradlew clean build -x test -Dspring.profiles.active=prod-oci
51+
52+
- name: Prepare File for Deployment
53+
run: |
54+
mkdir -p deployment/prod/build/libs
55+
cp ./docker/dockerfile-prod-oci ./docker/docker-compose-prod-oci.yaml deployment/prod/
56+
cp -r ./build/libs/yappu-world-prod-oci.jar deployment/prod/build/libs
57+
58+
# Github Action 실행 서버 IP 추출
59+
- name: Get Github Actions IP
60+
id: ip
61+
uses: candidob/[email protected]
62+
63+
# OCI CLI 설정
64+
- name: Setup OCI CLI
65+
run: |
66+
mkdir -p ~/.oci
67+
echo "${{ secrets.OCI_CLI_KEY_CONTENT }}" > ~/.oci/key.pem
68+
chmod 600 ~/.oci/key.pem
69+
70+
cat > ~/.oci/config << EOF
71+
[DEFAULT]
72+
user=${{ secrets.OCI_CLI_USER }}
73+
fingerprint=${{ secrets.OCI_CLI_FINGERPRINT }}
74+
tenancy=${{ secrets.OCI_CLI_TENANCY }}
75+
region=${{ secrets.OCI_CLI_REGION }}
76+
key_file=~/.oci/key.pem
77+
EOF
78+
79+
chmod 600 ~/.oci/config
80+
81+
# OCI CLI 설치
82+
curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh | bash -s -- --accept-all-defaults
83+
echo "$HOME/bin" >> $GITHUB_PATH
84+
~/bin/oci --version
85+
86+
# NSG에 Github Action 서버를 등록
87+
- name: Add Github Actions IP to OCI NSG
88+
run: |
89+
~/bin/oci network nsg rules add \
90+
--nsg-id ${{ secrets.OCI_PROD_NSG_OCID }} \
91+
--security-rules '[{
92+
"direction": "INGRESS",
93+
"protocol": "6",
94+
"source": "${{ steps.ip.outputs.ipv4 }}/32",
95+
"sourceType": "CIDR_BLOCK",
96+
"tcpOptions": {
97+
"destinationPortRange": {
98+
"min": 22,
99+
"max": 22
100+
}
101+
},
102+
"description": "GitHub Actions temporary access",
103+
"isStateless": false
104+
}]'
105+
106+
- name: Wait for NSG rule to propagate
107+
run: sleep 10
108+
109+
- name: Setup SSH Key
110+
run: |
111+
mkdir -p ~/.ssh
112+
echo "${{ secrets.OCI_PROD_SSH_PRIVATE_KEY }}" > ~/.ssh/oci_prod_key
113+
chmod 600 ~/.ssh/oci_prod_key
114+
115+
- name: Upload files to OCI Instance
116+
uses: appleboy/[email protected]
117+
with:
118+
host: ${{ secrets.OCI_PROD_INSTANCE_IP }}
119+
username: ubuntu
120+
key: ${{ secrets.OCI_PROD_SSH_PRIVATE_KEY }}
121+
source: "deployment/prod/*"
122+
target: "/home/ubuntu"
123+
124+
- name: Deploy using Docker Compose
125+
uses: appleboy/[email protected]
126+
with:
127+
host: ${{ secrets.OCI_PROD_INSTANCE_IP }}
128+
username: ubuntu
129+
key: ${{ secrets.OCI_PROD_SSH_PRIVATE_KEY }}
130+
script: |
131+
cd /home/ubuntu/deployment/prod
132+
docker-compose -f docker-compose-prod-oci.yaml down
133+
docker system prune -f
134+
docker-compose -f docker-compose-prod-oci.yaml build --no-cache
135+
docker-compose -f docker-compose-prod-oci.yaml up -d
136+
137+
- name: Remove Github Actions IP from OCI NSG
138+
if: always()
139+
run: |
140+
# NSG 규칙 ID 찾기
141+
RULE_ID=$(~/bin/oci network nsg rules list \
142+
--nsg-id ${{ secrets.OCI_PROD_NSG_OCID }} \
143+
--all \
144+
--query "data[?source=='${{ steps.ip.outputs.ipv4 }}/32' && direction=='INGRESS'].id | [0]" \
145+
--raw-output)
146+
147+
if [ ! -z "$RULE_ID" ] && [ "$RULE_ID" != "null" ]; then
148+
~/bin/oci network nsg rules remove \
149+
--nsg-id ${{ secrets.OCI_PROD_NSG_OCID }} \
150+
--security-rule-ids "[\"$RULE_ID\"]"
151+
fi
152+
153+
- name: Cleanup
154+
if: always()
155+
run: |
156+
rm -f ~/.oci/key.pem
157+
rm -f ~/.ssh/oci_prod_key
158+
159+
# Discord Notification
160+
- name: CD Success Notification
161+
uses: sarisia/actions-status-discord@v1
162+
if: success()
163+
with:
164+
title: ✅ OCI 상용 배포 성공 ✅
165+
webhook: ${{ secrets.DISCORD_WEBHOOK_URL }}
166+
color: 0x00FF00
167+
username: 페페훅
168+
169+
- name: CD Failure Notification
170+
uses: sarisia/actions-status-discord@v1
171+
if: failure()
172+
with:
173+
title: ❗️OCI 상용 배포 실패 ❗️
174+
webhook: ${{ secrets.DISCORD_WEBHOOK_URL }}
175+
color: 0xFF0000
176+
username: 페페훅
177+
178+
update_release:
179+
needs: build
180+
permissions:
181+
contents: write
182+
pull-requests: write
183+
runs-on: ubuntu-latest
184+
steps:
185+
- name: Update Release
186+
uses: release-drafter/release-drafter@v6
187+
with:
188+
config-name: release-drafter-config.yaml
189+
env:
190+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ dependencies {
3131
runtimeOnly("org.springframework.boot:spring-boot-docker-compose")
3232

3333
runtimeOnly("com.mysql:mysql-connector-j")
34+
runtimeOnly("com.oracle.database.jdbc:ojdbc11")
35+
runtimeOnly("com.oracle.database.security:oraclepki:23.5.0.24.07")
3436
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
3537
implementation("com.linecorp.kotlin-jdsl:jpql-dsl:3.5.5")
3638
implementation("com.linecorp.kotlin-jdsl:jpql-render:3.5.5")

docker/docker-compose-dev-oci.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
services:
2+
app:
3+
image: yappu-world-dev-oci
4+
container_name: yappu-world-dev-oci
5+
build:
6+
context: .
7+
dockerfile: dockerfile-dev-oci
8+
ports:
9+
- '8080:8080'
10+
volumes:
11+
- /opt/oracle/wallet:/wallet:ro

docker/docker-compose-dev.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ services:
77
dockerfile: dockerfile-dev
88
ports:
99
- '8080:8080'
10+
volumes:
11+
- /opt/oracle/wallet:/wallet:ro

0 commit comments

Comments
 (0)