Skip to content

Commit f78917f

Browse files
committed
Unify deployment secret names
1 parent c76fc7d commit f78917f

5 files changed

Lines changed: 201 additions & 236 deletions

File tree

.github/workflows/deploy-dev.yml

Lines changed: 66 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -52,42 +52,44 @@ jobs:
5252
needs: build-and-push
5353
runs-on: ubuntu-latest
5454
environment: development
55-
env:
56-
DEV_DEPLOY_DIR: ${{ secrets.DEV_DEPLOY_DIR || format('/home/{0}/OnTime-back-dev', secrets.DEV_REMOTE_USER) }}
5755
steps:
5856
- name: Checkout repository
5957
uses: actions/checkout@v4
6058

6159
- name: Prepare dev deploy directory
6260
uses: appleboy/ssh-action@v1.0.3
6361
with:
64-
host: ${{ secrets.DEV_REMOTE_HOST }}
65-
username: ${{ secrets.DEV_REMOTE_USER }}
66-
key: ${{ secrets.DEV_REMOTE_SSH_KEY }}
62+
host: ${{ secrets.REMOTE_HOST }}
63+
username: ${{ secrets.REMOTE_USER }}
64+
key: ${{ secrets.REMOTE_SSH_KEY }}
6765
script: |
6866
set -eu
69-
mkdir -p "${{ env.DEV_DEPLOY_DIR }}"
67+
[ "${{ secrets.DEPLOY_ENVIRONMENT }}" = "development" ] || {
68+
echo "Invalid development deployment secret scope." >&2
69+
exit 1
70+
}
71+
mkdir -p "${{ secrets.DEPLOY_DIR }}"
7072
7173
- name: Upload compose files to remote PC
7274
uses: appleboy/scp-action@v0.1.7
7375
with:
74-
host: ${{ secrets.DEV_REMOTE_HOST }}
75-
username: ${{ secrets.DEV_REMOTE_USER }}
76-
key: ${{ secrets.DEV_REMOTE_SSH_KEY }}
76+
host: ${{ secrets.REMOTE_HOST }}
77+
username: ${{ secrets.REMOTE_USER }}
78+
key: ${{ secrets.REMOTE_SSH_KEY }}
7779
source: "ontime-back/docker-compose.yml,ontime-back/docker-compose.dev.yml"
78-
target: ${{ env.DEV_DEPLOY_DIR }}
80+
target: ${{ secrets.DEPLOY_DIR }}
7981
strip_components: 1
8082

8183
- name: Pull image and restart dev containers
8284
uses: appleboy/ssh-action@v1.0.3
8385
with:
84-
host: ${{ secrets.DEV_REMOTE_HOST }}
85-
username: ${{ secrets.DEV_REMOTE_USER }}
86-
key: ${{ secrets.DEV_REMOTE_SSH_KEY }}
86+
host: ${{ secrets.REMOTE_HOST }}
87+
username: ${{ secrets.REMOTE_USER }}
88+
key: ${{ secrets.REMOTE_SSH_KEY }}
8789
script: |
8890
set -eu
8991
90-
DEPLOY_DIR="${{ env.DEV_DEPLOY_DIR }}"
92+
DEPLOY_DIR="${{ secrets.DEPLOY_DIR }}"
9193
CONTAINER_NAME="ontime-dev-container"
9294
9395
mkdir -p "$DEPLOY_DIR"
@@ -98,47 +100,71 @@ jobs:
98100
IMAGE_TAG=${{ env.IMAGE_TAG }}
99101
BACKEND_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
100102
BACKEND_CONTAINER_NAME=ontime-dev-container
101-
BACKEND_HTTP_PORT=${{ secrets.DEV_BACKEND_HTTP_PORT || '8081' }}
102-
BACKEND_MEMORY_LIMIT=${{ secrets.DEV_BACKEND_MEMORY_LIMIT || '768m' }}
103-
BACKEND_CPU_LIMIT=${{ secrets.DEV_BACKEND_CPU_LIMIT || '1.0' }}
103+
BACKEND_HTTP_PORT=${{ secrets.BACKEND_HTTP_PORT }}
104+
BACKEND_MEMORY_LIMIT=${{ secrets.BACKEND_MEMORY_LIMIT }}
105+
BACKEND_CPU_LIMIT=${{ secrets.BACKEND_CPU_LIMIT }}
104106
SERVER_PORT=8080
105107
SPRING_PROFILES_ACTIVE=dev
106108
JAVA_TOOL_OPTIONS=-XX:InitialRAMPercentage=50.0 -XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/./urandom
107109
108-
MYSQL_DATABASE=${{ secrets.DEV_MYSQL_DATABASE || 'ontime_dev' }}
109-
MYSQL_USER=${{ secrets.DEV_MYSQL_USER || 'ontime_dev' }}
110-
MYSQL_PASSWORD=${{ secrets.DEV_MYSQL_PASSWORD || 'ontime_dev_password' }}
111-
MYSQL_ROOT_PASSWORD=${{ secrets.DEV_MYSQL_ROOT_PASSWORD || 'ontime_dev_root_password' }}
110+
MYSQL_DATABASE=${{ secrets.MYSQL_DATABASE }}
111+
MYSQL_USER=${{ secrets.MYSQL_USER }}
112+
MYSQL_PASSWORD=${{ secrets.MYSQL_PASSWORD }}
113+
MYSQL_ROOT_PASSWORD=${{ secrets.MYSQL_ROOT_PASSWORD }}
112114
113-
SPRING_APPLICATION_NAME=${{ secrets.DEV_SPRING_APPLICATION_NAME || 'ontime-back-dev' }}
114-
SPRING_DATASOURCE_URL=${{ secrets.DEV_SPRING_DATASOURCE_URL || 'jdbc:mysql://mysql:3306/ontime_dev?useSSL=false&serverTimezone=Asia/Seoul&characterEncoding=UTF-8&allowPublicKeyRetrieval=true' }}
115-
SPRING_DATASOURCE_USERNAME=${{ secrets.DEV_SPRING_DATASOURCE_USERNAME || secrets.DEV_MYSQL_USER || 'ontime_dev' }}
116-
SPRING_DATASOURCE_PASSWORD=${{ secrets.DEV_SPRING_DATASOURCE_PASSWORD || secrets.DEV_MYSQL_PASSWORD || 'ontime_dev_password' }}
115+
SPRING_APPLICATION_NAME=${{ secrets.SPRING_APPLICATION_NAME }}
116+
SPRING_DATASOURCE_URL=${{ secrets.SPRING_DATASOURCE_URL }}
117+
SPRING_DATASOURCE_USERNAME=${{ secrets.SPRING_DATASOURCE_USERNAME }}
118+
SPRING_DATASOURCE_PASSWORD=${{ secrets.SPRING_DATASOURCE_PASSWORD }}
117119
SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver
118120
SPRING_JPA_HIBERNATE_DDL_AUTO=validate
119121
120122
SPRING_FLYWAY_ENABLED=true
121123
SPRING_FLYWAY_BASELINE_ON_MIGRATE=false
122124
123-
JWT_SECRET_KEY=${{ secrets.DEV_JWT_SECRETKEY || 'dev_secret_key_for_ontime_back_remote_pc_development_1234567890' }}
124-
JWT_ACCESS_EXPIRATION=${{ secrets.DEV_JWT_ACCESS_EXPIRATION || '3600000' }}
125-
JWT_REFRESH_EXPIRATION=${{ secrets.DEV_JWT_REFRESH_EXPIRATION || '1209600000' }}
126-
JWT_ACCESS_HEADER=${{ secrets.DEV_JWT_ACCESS_HEADER || 'Authorization' }}
127-
JWT_REFRESH_HEADER=${{ secrets.DEV_JWT_REFRESH_HEADER || 'Authorization-refresh' }}
125+
JWT_SECRET_KEY=${{ secrets.JWT_SECRETKEY }}
126+
JWT_ACCESS_EXPIRATION=${{ secrets.JWT_ACCESS_EXPIRATION }}
127+
JWT_REFRESH_EXPIRATION=${{ secrets.JWT_REFRESH_EXPIRATION }}
128+
JWT_ACCESS_HEADER=${{ secrets.JWT_ACCESS_HEADER }}
129+
JWT_REFRESH_HEADER=${{ secrets.JWT_REFRESH_HEADER }}
128130
129-
GOOGLE_WEB_CLIENT_ID=${{ secrets.GOOGLE_WEB_CLIENT_ID || 'dev-google-web-client-id' }}
130-
GOOGLE_APP_CLIENT_ID=${{ secrets.GOOGLE_APP_CLIENT_ID || 'dev-google-app-client-id' }}
131+
GOOGLE_WEB_CLIENT_ID=${{ secrets.GOOGLE_WEB_CLIENT_ID }}
132+
GOOGLE_APP_CLIENT_ID=${{ secrets.GOOGLE_APP_CLIENT_ID }}
131133
132-
APPLE_CLIENT_ID=${{ secrets.DEV_APPLE_CLIENT_ID || 'dev-apple-client-id' }}
133-
APPLE_TEAM_ID=${{ secrets.DEV_APPLE_TEAM_ID || 'dev-apple-team-id' }}
134-
APPLE_LOGIN_KEY=${{ secrets.DEV_APPLE_LOGIN_KEY || 'dev-apple-key-id' }}
135-
APPLE_PRIVATE_KEY_BASE64=${{ secrets.DEV_APPLE_PRIVATE_KEY_BASE64 }}
136-
FEATURE_APPLE_LOGIN_ENABLED=${{ secrets.DEV_FEATURE_APPLE_LOGIN_ENABLED || 'false' }}
134+
APPLE_CLIENT_ID=${{ secrets.APPLE_CLIENT_ID }}
135+
APPLE_TEAM_ID=${{ secrets.APPLE_TEAM_ID }}
136+
APPLE_LOGIN_KEY=${{ secrets.APPLE_LOGIN_KEY }}
137+
APPLE_PRIVATE_KEY_BASE64=${{ secrets.APPLE_PRIVATE_KEY_BASE64 }}
138+
FEATURE_APPLE_LOGIN_ENABLED=${{ secrets.FEATURE_APPLE_LOGIN_ENABLED }}
137139
138-
FIREBASE_CREDENTIALS_BASE64=${{ secrets.DEV_FIREBASE_CREDENTIALS_BASE64 }}
140+
FIREBASE_CREDENTIALS_BASE64=${{ secrets.FIREBASE_CREDENTIALS_BASE64 }}
139141
EOF
140142
141-
echo "${{ secrets.GHCR_READ_TOKEN }}" | sudo docker login ghcr.io -u "${{ secrets.GHCR_USERNAME }}" --password-stdin
143+
fail_deploy() {
144+
echo "Unsafe development configuration: $1" >&2
145+
exit 1
146+
}
147+
148+
get_env_value() {
149+
grep -E "^$1=" .env | tail -n 1 | cut -d= -f2-
150+
}
151+
152+
DB_URL="$(get_env_value SPRING_DATASOURCE_URL)"
153+
BACKEND_HTTP_BIND="$(get_env_value BACKEND_HTTP_PORT)"
154+
DB_URL_NO_PREFIX="${DB_URL#jdbc:mysql://}"
155+
[ "$DB_URL_NO_PREFIX" != "$DB_URL" ] || fail_deploy "SPRING_DATASOURCE_URL must start with jdbc:mysql://."
156+
DB_ADDRESS="${DB_URL_NO_PREFIX%%/*}"
157+
DB_HOST="${DB_ADDRESS%%:*}"
158+
DB_NAME_AND_QUERY="${DB_URL_NO_PREFIX#*/}"
159+
DB_NAME="$(printf '%s' "$DB_NAME_AND_QUERY" | sed 's/[?;].*$//')"
160+
161+
[ "${{ secrets.DEPLOY_ENVIRONMENT }}" = "development" ] || fail_deploy "DEPLOY_ENVIRONMENT must be development."
162+
[ -n "$DB_URL" ] || fail_deploy "SPRING_DATASOURCE_URL is required."
163+
[ "$DB_HOST" = "mysql" ] || fail_deploy "SPRING_DATASOURCE_URL must point to the Compose mysql service."
164+
[ "$DB_NAME" = "ontime_dev" ] || fail_deploy "SPRING_DATASOURCE_URL must use the ontime_dev database."
165+
[ "$BACKEND_HTTP_BIND" != "127.0.0.1:8080" ] || fail_deploy "BACKEND_HTTP_PORT looks like the production bind."
166+
167+
echo "${{ secrets.GITHUB_TOKEN }}" | sudo docker login ghcr.io -u "${{ github.actor }}" --password-stdin
142168
143169
if sudo docker compose version >/dev/null 2>&1; then
144170
COMPOSE="sudo docker compose"
@@ -166,4 +192,4 @@ jobs:
166192
exit 1
167193
fi
168194
169-
curl -fsS "http://127.0.0.1:${{ secrets.DEV_BACKEND_HTTP_PORT || '8081' }}/actuator/health/readiness"
195+
curl -fsS "http://127.0.0.1:${{ secrets.BACKEND_HTTP_PORT }}/actuator/health/readiness"

.github/workflows/deploy.yml

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,33 +60,33 @@ jobs:
6060
- name: Upload compose file to EC2
6161
uses: appleboy/scp-action@v0.1.7
6262
with:
63-
host: ${{ secrets.EC2_HOST }}
64-
username: ${{ secrets.EC2_USER }}
65-
key: ${{ secrets.EC2_SSH_KEY }}
63+
host: ${{ secrets.REMOTE_HOST }}
64+
username: ${{ secrets.REMOTE_USER }}
65+
key: ${{ secrets.REMOTE_SSH_KEY }}
6666
source: "ontime-back/docker-compose.yml"
67-
target: "/home/ubuntu/OnTime-back"
67+
target: ${{ secrets.DEPLOY_DIR }}
6868
strip_components: 1
6969

7070
- name: Upload Caddyfile to EC2
7171
uses: appleboy/scp-action@v0.1.7
7272
with:
73-
host: ${{ secrets.EC2_HOST }}
74-
username: ${{ secrets.EC2_USER }}
75-
key: ${{ secrets.EC2_SSH_KEY }}
73+
host: ${{ secrets.REMOTE_HOST }}
74+
username: ${{ secrets.REMOTE_USER }}
75+
key: ${{ secrets.REMOTE_SSH_KEY }}
7676
source: "ontime-back/Caddyfile"
77-
target: "/home/ubuntu/OnTime-back"
77+
target: ${{ secrets.DEPLOY_DIR }}
7878
strip_components: 1
7979

8080
- name: Pull image and restart container
8181
uses: appleboy/ssh-action@v1.0.3
8282
with:
83-
host: ${{ secrets.EC2_HOST }}
84-
username: ${{ secrets.EC2_USER }}
85-
key: ${{ secrets.EC2_SSH_KEY }}
83+
host: ${{ secrets.REMOTE_HOST }}
84+
username: ${{ secrets.REMOTE_USER }}
85+
key: ${{ secrets.REMOTE_SSH_KEY }}
8686
script: |
8787
set -eu
8888
89-
DEPLOY_DIR="/home/ubuntu/OnTime-back"
89+
DEPLOY_DIR="${{ secrets.DEPLOY_DIR }}"
9090
CONTAINER_NAME="ontime-container"
9191
PUBLIC_BACKEND_HOST="${{ env.PUBLIC_BACKEND_HOST }}"
9292
@@ -98,9 +98,9 @@ jobs:
9898
IMAGE_TAG=${{ env.IMAGE_TAG }}
9999
BACKEND_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
100100
BACKEND_CONTAINER_NAME=ontime-container
101-
BACKEND_HTTP_PORT=${{ secrets.BACKEND_HTTP_PORT || '127.0.0.1:8080' }}
102-
BACKEND_MEMORY_LIMIT=${{ secrets.BACKEND_MEMORY_LIMIT || '768m' }}
103-
BACKEND_CPU_LIMIT=${{ secrets.BACKEND_CPU_LIMIT || '1.0' }}
101+
BACKEND_HTTP_PORT=${{ secrets.BACKEND_HTTP_PORT }}
102+
BACKEND_MEMORY_LIMIT=${{ secrets.BACKEND_MEMORY_LIMIT }}
103+
BACKEND_CPU_LIMIT=${{ secrets.BACKEND_CPU_LIMIT }}
104104
SERVER_PORT=8080
105105
SPRING_PROFILES_ACTIVE=prod
106106
JAVA_TOOL_OPTIONS=-XX:InitialRAMPercentage=50.0 -XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/./urandom
@@ -147,7 +147,7 @@ jobs:
147147
APPLE_TEAM_ID=${{ secrets.APPLE_TEAM_ID }}
148148
APPLE_LOGIN_KEY=${{ secrets.APPLE_LOGIN_KEY }}
149149
APPLE_PRIVATE_KEY_BASE64=${{ secrets.APPLE_PRIVATE_KEY_BASE64 }}
150-
FEATURE_APPLE_LOGIN_ENABLED=${{ secrets.FEATURE_APPLE_LOGIN_ENABLED || 'true' }}
150+
FEATURE_APPLE_LOGIN_ENABLED=${{ secrets.FEATURE_APPLE_LOGIN_ENABLED }}
151151
152152
FIREBASE_CREDENTIALS_BASE64=${{ secrets.FIREBASE_CREDENTIALS_BASE64 }}
153153
EOF
@@ -200,6 +200,7 @@ jobs:
200200
[ -n "$DB_USERNAME" ] || fail_deploy "SPRING_DATASOURCE_USERNAME is required."
201201
[ -n "$DB_PASSWORD" ] || fail_deploy "SPRING_DATASOURCE_PASSWORD is required."
202202
[ -n "$DB_HOST" ] || fail_deploy "SPRING_DATASOURCE_URL must include an RDS host."
203+
[ "${{ secrets.DEPLOY_ENVIRONMENT }}" = "production" ] || fail_deploy "DEPLOY_ENVIRONMENT must be production."
203204
[ "$DB_NAME" = "ontime_prod" ] || fail_deploy "SPRING_DATASOURCE_URL must use the ontime_prod database."
204205
[ "$NORMALIZED_DB_USERNAME" != "root" ] || fail_deploy "SPRING_DATASOURCE_USERNAME must not be root."
205206
[ "$BACKEND_HTTP_BIND" = "127.0.0.1:8080" ] || fail_deploy "BACKEND_HTTP_PORT must be 127.0.0.1:8080 so public traffic goes through Caddy HTTPS."

.github/workflows/ops-tail-production-logs.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ jobs:
1414
- name: Tail production backend logs
1515
uses: appleboy/ssh-action@v1.0.3
1616
with:
17-
host: ${{ secrets.EC2_HOST }}
18-
username: ${{ secrets.EC2_USER }}
19-
key: ${{ secrets.EC2_SSH_KEY }}
17+
host: ${{ secrets.REMOTE_HOST }}
18+
username: ${{ secrets.REMOTE_USER }}
19+
key: ${{ secrets.REMOTE_SSH_KEY }}
2020
script: |
2121
set -eu
2222
sudo docker logs --since 30m --tail=500 ontime-container \
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Use Shared Secret Names With Environment Overrides
2+
3+
Production and development deployment workflows use the same secret names and rely on the selected GitHub Environment to override only values that differ. This avoids duplicating environment identity in names like `DEV_REMOTE_HOST` and `EC2_HOST`, keeps genuinely shared values in one repository secret, and prevents future deploy fixes from updating one environment naming scheme but missing the other.
4+
5+
Environment-specific values belong in `development` or `production` Environment secrets. Values shared by every environment should be workflow constants, repository variables, repository secrets, or the built-in `GITHUB_TOKEN` depending on whether they are sensitive. Deploy workflows include environment sentinel and datasource checks because GitHub falls back from missing Environment secrets to repository secrets.

0 commit comments

Comments
 (0)