11name : Deploy
22
33on :
4+ workflow_dispatch :
45 push :
56 branches :
6- - deploy
7+ - main
78
89permissions :
910 contents : read
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
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
0 commit comments