Skip to content

Commit e1c3885

Browse files
authored
Merge pull request #297 from DevKor-github/dev
[codex] Align git workflow and deployments
2 parents 244b967 + 30400f0 commit e1c3885

6 files changed

Lines changed: 284 additions & 74 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
name: Deploy
22

33
on:
4+
workflow_dispatch:
45
push:
56
branches:
6-
- deploy
7+
- main
78

89
permissions:
910
contents: read
@@ -50,6 +51,7 @@ jobs:
5051
deploy-to-ec2:
5152
needs: build-and-push
5253
runs-on: ubuntu-latest
54+
environment: production
5355
steps:
5456
- name: Checkout repository
5557
uses: actions/checkout@v4
@@ -85,6 +87,8 @@ jobs:
8587
BACKEND_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
8688
BACKEND_CONTAINER_NAME=ontime-container
8789
BACKEND_HTTP_PORT=${{ secrets.BACKEND_HTTP_PORT || '8080' }}
90+
BACKEND_MEMORY_LIMIT=${{ secrets.BACKEND_MEMORY_LIMIT || '768m' }}
91+
BACKEND_CPU_LIMIT=${{ secrets.BACKEND_CPU_LIMIT || '1.0' }}
8892
SERVER_PORT=8080
8993
SPRING_PROFILES_ACTIVE=prod
9094
JAVA_TOOL_OPTIONS=-XX:InitialRAMPercentage=50.0 -XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/./urandom
@@ -152,14 +156,33 @@ jobs:
152156
FLYWAY_BASELINE="$(get_env_value SPRING_FLYWAY_BASELINE_ON_MIGRATE)"
153157
NORMALIZED_DB_URL="$(printf '%s' "$DB_URL" | tr '[:upper:]' '[:lower:]')"
154158
NORMALIZED_DB_USERNAME="$(printf '%s' "$DB_USERNAME" | tr '[:upper:]' '[:lower:]')"
159+
DB_URL_NO_PREFIX="${DB_URL#jdbc:mysql://}"
160+
[ "$DB_URL_NO_PREFIX" != "$DB_URL" ] || fail_deploy "SPRING_DATASOURCE_URL must start with jdbc:mysql://."
161+
DB_ADDRESS="${DB_URL_NO_PREFIX%%/*}"
162+
DB_HOST="${DB_ADDRESS%%:*}"
163+
DB_PORT="${DB_ADDRESS#*:}"
164+
[ "$DB_PORT" != "$DB_ADDRESS" ] || DB_PORT="3306"
165+
DB_NAME_AND_QUERY="${DB_URL_NO_PREFIX#*/}"
166+
DB_NAME="$(printf '%s' "$DB_NAME_AND_QUERY" | sed 's/[?;].*$//')"
155167
156168
[ -n "$DB_URL" ] || fail_deploy "SPRING_DATASOURCE_URL is required."
157169
[ -n "$DB_USERNAME" ] || fail_deploy "SPRING_DATASOURCE_USERNAME is required."
158170
[ -n "$DB_PASSWORD" ] || fail_deploy "SPRING_DATASOURCE_PASSWORD is required."
171+
[ -n "$DB_HOST" ] || fail_deploy "SPRING_DATASOURCE_URL must include an RDS host."
172+
[ "$DB_NAME" = "ontime_prod" ] || fail_deploy "SPRING_DATASOURCE_URL must use the ontime_prod database."
159173
[ "$NORMALIZED_DB_USERNAME" != "root" ] || fail_deploy "SPRING_DATASOURCE_USERNAME must not be root."
160174
[ "$DDL_AUTO" = "validate" ] || fail_deploy "SPRING_JPA_HIBERNATE_DDL_AUTO must be validate."
161175
[ "$FLYWAY_BASELINE" = "false" ] || fail_deploy "SPRING_FLYWAY_BASELINE_ON_MIGRATE must be false."
162176
177+
case "$NORMALIZED_DB_URL" in
178+
*localhost*|*127.0.0.1*|*host.docker.internal*) fail_deploy "SPRING_DATASOURCE_URL must point to private RDS, not a local database." ;;
179+
esac
180+
181+
case "$(printf '%s' "$DB_HOST" | tr '[:upper:]' '[:lower:]')" in
182+
*.rds.amazonaws.com) ;;
183+
*) fail_deploy "SPRING_DATASOURCE_URL host must be an RDS endpoint." ;;
184+
esac
185+
163186
case "$NORMALIZED_DB_URL" in
164187
*allowpublickeyretrieval=true*) fail_deploy "SPRING_DATASOURCE_URL must not enable allowPublicKeyRetrieval." ;;
165188
esac
@@ -173,10 +196,17 @@ jobs:
173196
esac
174197
175198
case "$NORMALIZED_DB_URL" in
176-
*sslmode=required*|*sslmode=verify_ca*|*sslmode=verify_identity*) ;;
177-
*) fail_deploy "SPRING_DATASOURCE_URL must declare sslMode=REQUIRED, VERIFY_CA, or VERIFY_IDENTITY." ;;
199+
*sslmode=required*|*sslmode=verify_ca*|*sslmode=verify_identity*|*usessl=true*) ;;
200+
*) fail_deploy "SPRING_DATASOURCE_URL must declare useSSL=true, sslMode=REQUIRED, VERIFY_CA, or VERIFY_IDENTITY." ;;
178201
esac
179202
203+
echo "Checking EC2-to-RDS TCP connectivity for $DB_HOST:$DB_PORT..."
204+
if command -v nc >/dev/null 2>&1; then
205+
nc -zv "$DB_HOST" "$DB_PORT"
206+
else
207+
timeout 5 bash -c "</dev/tcp/$DB_HOST/$DB_PORT"
208+
fi
209+
180210
echo "${{ secrets.GHCR_READ_TOKEN }}" | sudo docker login ghcr.io -u "${{ secrets.GHCR_USERNAME }}" --password-stdin
181211
182212
if sudo docker compose version >/dev/null 2>&1; then

.github/workflows/test.yml

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
# PR이 올라왔을 때 자동으로 테스트코드를 실행하고 하나라도 Fail했을 시, PR을 Close하고 실패 코멘트를 달고 성공시에는 머지를 가능케하는 파이프라인.
1+
# PR이 올라왔을 때 자동으로 테스트코드를 실행하고 실패 시 머지를 막는 파이프라인.
22
name: PR Test
33

44
on:
55
pull_request:
66
branches:
7-
- main # main 브랜치로 머지되는 PR에서 실행
7+
- dev
8+
- main
89

910
jobs:
1011
test:
1112
runs-on: ubuntu-latest
12-
outputs:
13-
test_result: ${{ steps.run-tests.outcome }} # 테스트 결과를 output으로 저장
1413

1514
services:
1615
mysql:
@@ -64,8 +63,6 @@ jobs:
6463
6564
# 4. Gradle 빌드 & JUnit 테스트 실행
6665
- name: Run Tests with Gradle
67-
id: run-tests # 실행 결과를 output으로 저장할 id 추가
68-
continue-on-error: true
6966
env:
7067
SPRING_PROFILES_ACTIVE: test
7168
run: |
@@ -76,43 +73,3 @@ jobs:
7673
run: |
7774
echo "Checking Flyway migration history..."
7875
mysql -h 127.0.0.1 -u test_user --password=test_password -e "SELECT * FROM test_db.flyway_schema_history;"
79-
80-
81-
handle-failure:
82-
needs: test
83-
if: needs.test.outputs.test_result == 'failure' # test job의 output 값이 실패(failure)일 때 실행
84-
runs-on: ubuntu-latest
85-
permissions:
86-
pull-requests: write
87-
issues: write
88-
steps:
89-
- name: Close PR
90-
uses: octokit/request-action@v2.x
91-
with:
92-
route: PATCH /repos/{owner}/{repo}/pulls/{pull_number}
93-
owner: ${{ github.repository_owner }}
94-
repo: ${{ github.event.repository.name }}
95-
pull_number: ${{ github.event.pull_request.number }}
96-
state: closed
97-
env:
98-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
99-
100-
- name: Wait for PR to close
101-
run: sleep 5
102-
103-
- name: Comment on PR
104-
uses: actions/github-script@v6
105-
with:
106-
github-token: ${{ secrets.GITHUB_TOKEN }}
107-
script: |
108-
const prNumber = context.payload.pull_request?.number || context.payload.issue?.number;
109-
if (!prNumber) {
110-
console.log("PR 번호를 찾을 수 없습니다.");
111-
return;
112-
}
113-
github.rest.issues.createComment({
114-
owner: context.repo.owner,
115-
repo: context.repo.repo,
116-
issue_number: prNumber,
117-
body: "실패하는 테스트코드가 있어 PR이 자동으로 닫혔습니다.\nGithub Action에서 자세한 실패 로그를 확인하고 코드를 수정하세요."
118-
});

docs/deployment.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,24 @@ Deployment access:
1515
Runtime image and port:
1616

1717
- `BACKEND_HTTP_PORT` (optional, defaults to `8080`)
18+
- `BACKEND_MEMORY_LIMIT` (optional, defaults to `768m`; use `640m` if the EC2 instance is memory constrained)
19+
- `BACKEND_CPU_LIMIT` (optional, defaults to `1.0`)
1820

1921
Spring and database:
2022

2123
- `SPRING_APPLICATION_NAME`
22-
- `SPRING_DATASOURCE_URL`
23-
- `SPRING_DATASOURCE_USERNAME`
24+
- `SPRING_DATASOURCE_URL` (`jdbc:mysql://ontime-prod.cpoeguokwaq5.ap-northeast-2.rds.amazonaws.com:3306/ontime_prod?useSSL=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8`)
25+
- `SPRING_DATASOURCE_USERNAME` (`ontimeadmin`)
2426
- `SPRING_DATASOURCE_PASSWORD`
25-
- `SPRING_DATASOURCE_DRIVER_CLASS_NAME`
26-
- `SPRING_JPA_HIBERNATE_DDL_AUTO`
27-
- `SPRING_FLYWAY_URL`
28-
- `SPRING_FLYWAY_USER`
29-
- `SPRING_FLYWAY_PASSWORD`
27+
28+
The deploy workflow hardcodes safe production defaults for the datasource driver, JPA DDL mode, and Flyway:
29+
30+
- `SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver`
31+
- `SPRING_JPA_HIBERNATE_DDL_AUTO=validate`
32+
- `SPRING_FLYWAY_ENABLED=true`
33+
- `SPRING_FLYWAY_BASELINE_ON_MIGRATE=false`
34+
35+
It also fails before restart if the datasource URL does not point to an RDS MySQL endpoint using the `ontime_prod` database, or if EC2 cannot reach RDS on `3306`.
3036

3137
Authentication and OAuth:
3238

@@ -77,7 +83,9 @@ base64 -i ontime-back/src/main/resources/key/AuthKey_743M7R5W3W.p8 | tr -d '\n'
7783

7884
## Build And Release Flow
7985

80-
Push to the `deploy` branch to trigger `.github/workflows/deploy.yml`.
86+
Push to the `main` branch, or run `.github/workflows/deploy.yml` manually, to deploy production.
87+
88+
Pushes to `dev` run CI only. There is no dev-server deploy workflow in the one-EC2 plan.
8189

8290
The workflow:
8391

@@ -87,8 +95,9 @@ The workflow:
8795
- `ghcr.io/devkor-github/ontime-back:deploy-latest`
8896
3. Uploads `docker-compose.yml` to `/home/ubuntu/OnTime-back`.
8997
4. Writes `/home/ubuntu/OnTime-back/.env` from GitHub secrets.
90-
5. Runs `docker compose pull && docker compose up -d --remove-orphans`.
91-
6. Waits until the `ontime-container` Docker health status is `healthy`.
98+
5. Verifies EC2 can reach private RDS on `3306`.
99+
6. Runs `docker compose pull && docker compose up -d --remove-orphans`.
100+
7. Waits until the `ontime-container` Docker health status is `healthy`.
92101

93102
## Health Verification
94103

@@ -105,6 +114,7 @@ cd /home/ubuntu/OnTime-back
105114
sudo docker compose ps
106115
sudo docker inspect -f '{{.State.Health.Status}}' ontime-container
107116
curl -fsS http://localhost:8080/actuator/health/readiness
117+
nc -zv ontime-prod.cpoeguokwaq5.ap-northeast-2.rds.amazonaws.com 3306
108118
```
109119

110120
## Rollback

0 commit comments

Comments
 (0)