forked from baron/baron-sso
Merge pull request 'dev-stagingcd-fix' (#235) from dev-stagingcd-fix into dev
Reviewed-on: ai-team/baron-sso#235
This commit is contained in:
@@ -106,11 +106,6 @@ jobs:
|
|||||||
provenance: false
|
provenance: false
|
||||||
sbom: false
|
sbom: false
|
||||||
|
|
||||||
- name: Temporarily update userfront nginx port
|
|
||||||
run: |
|
|
||||||
sed -i 's/listen 5000;/listen 80;/g' userfront/nginx.conf
|
|
||||||
sed -i 's/proxy_pass http:\/\/baron_backend:3000;/proxy_pass http:\/\/baron_backend:3010;/g' userfront/nginx.conf
|
|
||||||
|
|
||||||
- name: Build and push userfront RC image
|
- name: Build and push userfront RC image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -45,26 +45,35 @@ jobs:
|
|||||||
|
|
||||||
# Sanity check
|
# Sanity check
|
||||||
if [ -z "${STAGE_USER}" ] || [ -z "${STAGE_HOST}" ] || [ -z "${DEPLOY_PATH}" ]; then
|
if [ -z "${STAGE_USER}" ] || [ -z "${STAGE_HOST}" ] || [ -z "${DEPLOY_PATH}" ]; then
|
||||||
echo "::error::Missing required vars (STAGE_USER/STAGE_HOST/DEPLOY_PATH). Check Gitea repo variables."
|
echo "::error::Missing required vars (STAGE_USER/STAGE_HOST/DEPLOY_PATH)."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ssh-keyscan -H "${STAGE_HOST}" >> ~/.ssh/known_hosts
|
ssh-keyscan -H "${STAGE_HOST}" >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
ssh "${STAGE_USER}@${STAGE_HOST}" "mkdir -p '${DEPLOY_PATH}'"
|
ssh "${STAGE_USER}@${STAGE_HOST}" "mkdir -p '${DEPLOY_PATH}'"
|
||||||
|
|
||||||
# Create .env for Staging using a HEREDOC to prevent shell expansion issues
|
# .env 파일 생성
|
||||||
cat <<'EOF' > .env
|
cat <<'EOF' > .env
|
||||||
APP_ENV=stage
|
APP_ENV=${{ vars.APP_ENV }}
|
||||||
TZ=Asia/Seoul
|
TZ=Asia/Seoul
|
||||||
IDP_PROVIDER=ory
|
IDP_PROVIDER=ory
|
||||||
|
|
||||||
|
# DB & Clickhouse
|
||||||
DB_PORT=${{ vars.DB_PORT }}
|
DB_PORT=${{ vars.DB_PORT }}
|
||||||
CLICKHOUSE_PORT_HTTP=${{ vars.CLICKHOUSE_PORT_HTTP }}
|
CLICKHOUSE_PORT_HTTP=${{ vars.CLICKHOUSE_PORT_HTTP }}
|
||||||
CLICKHOUSE_PORT_NATIVE=${{ vars.CLICKHOUSE_PORT_NATIVE }}
|
CLICKHOUSE_PORT_NATIVE=${{ vars.CLICKHOUSE_PORT_NATIVE }}
|
||||||
|
CLICKHOUSE_HOST=${{ vars.CLICKHOUSE_HOST }}
|
||||||
|
CLICKHOUSE_USER=${{ vars.CLICKHOUSE_USER }}
|
||||||
|
CLICKHOUSE_PASSWORD=${{ vars.CLICKHOUSE_PASSWORD }}
|
||||||
|
|
||||||
|
|
||||||
BACKEND_PORT=${{ vars.BACKEND_PORT }}
|
BACKEND_PORT=${{ vars.BACKEND_PORT }}
|
||||||
ADMINFRONT_PORT=${{ vars.ADMINFRONT_PORT }}
|
ADMINFRONT_PORT=${{ vars.ADMINFRONT_PORT }}
|
||||||
DEVFRONT_PORT=${{ vars.DEVFRONT_PORT }}
|
DEVFRONT_PORT=${{ vars.DEVFRONT_PORT }}
|
||||||
USERFRONT_PORT=${{ vars.USERFRONT_PORT }}
|
USERFRONT_PORT=${{ vars.USERFRONT_PORT }}
|
||||||
|
|
||||||
|
OATHKEEPER_API_URL=${{ vars.OATHKEEPER_API_URL }}
|
||||||
|
|
||||||
DB_USER=${{ vars.DB_USER }}
|
DB_USER=${{ vars.DB_USER }}
|
||||||
DB_PASSWORD=${{ secrets.STG_DB_PASSWORD }}
|
DB_PASSWORD=${{ secrets.STG_DB_PASSWORD }}
|
||||||
DB_NAME=${{ vars.DB_NAME }}
|
DB_NAME=${{ vars.DB_NAME }}
|
||||||
@@ -117,20 +126,29 @@ jobs:
|
|||||||
OATHKEEPER_HEALTH_ENABLED=${{ vars.OATHKEEPER_HEALTH_ENABLED }}
|
OATHKEEPER_HEALTH_ENABLED=${{ vars.OATHKEEPER_HEALTH_ENABLED }}
|
||||||
CSRF_COOKIE_NAME=${{ vars.CSRF_COOKIE_NAME }}
|
CSRF_COOKIE_NAME=${{ vars.CSRF_COOKIE_NAME }}
|
||||||
CSRF_COOKIE_SECRET=${{ secrets.STG_CSRF_COOKIE_SECRET }}
|
CSRF_COOKIE_SECRET=${{ secrets.STG_CSRF_COOKIE_SECRET }}
|
||||||
OATHKEEPER_INTROSPECT_CLIENT_ID=${{ vars.OATHKEEPER_INTROSPECT_CLIENT_ID }}
|
# OATHKEEPER_INTROSPECT_CLIENT_ID=${{ vars.OATHKEEPER_INTROSPECT_CLIENT_ID }}
|
||||||
OATHKEEPER_INTROSPECT_CLIENT_SECRET=${{ secrets.STG_OATHKEEPER_INTROSPECT_CLIENT_SECRET }}
|
# OATHKEEPER_INTROSPECT_CLIENT_SECRET=${{ secrets.STG_OATHKEEPER_INTROSPECT_CLIENT_SECRET }}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Copy artifacts to remote
|
# 파일 복사
|
||||||
# Using compose.infra.yaml as base for staging (assuming simplified structure compared to prod)
|
ssh "${STAGE_USER}@${STAGE_HOST}" "mkdir -p ${DEPLOY_PATH}/docker"
|
||||||
# OR use docker-compose.template.yaml if staging follows prod structure strictly
|
|
||||||
scp docker/docker-compose.staging.template.yaml .env "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/"
|
# [중요] docker/ory 폴더 복사 (여기에 init-db/1-createdb.sql이 있어야 함)
|
||||||
scp docker/compose.infra.yaml "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/compose.infra.yml"
|
|
||||||
# Ory compose files might be needed too
|
|
||||||
scp docker/compose.ory.yaml "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/compose.ory.yml"
|
|
||||||
scp -r docker/ory "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/docker/"
|
scp -r docker/ory "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/docker/"
|
||||||
|
|
||||||
# Deploy
|
if [ -d "docker/init-metadata" ]; then
|
||||||
|
scp -r docker/init-metadata "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/docker/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "gateway" ]; then
|
||||||
|
scp -r gateway "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
scp docker/docker-compose.staging.template.yaml .env "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/"
|
||||||
|
scp docker/compose.infra.yaml "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/compose.infra.yml"
|
||||||
|
scp docker/compose.ory.yaml "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/compose.ory.yml"
|
||||||
|
|
||||||
|
# 배포 실행
|
||||||
echo "${HARBOR_ROBOT_KEY}" | ssh "${STAGE_USER}@${STAGE_HOST}" \
|
echo "${HARBOR_ROBOT_KEY}" | ssh "${STAGE_USER}@${STAGE_HOST}" \
|
||||||
"export DEPLOY_PATH='${DEPLOY_PATH}'; \
|
"export DEPLOY_PATH='${DEPLOY_PATH}'; \
|
||||||
export BACKEND_IMAGE_NAME='${BACKEND_IMAGE_NAME}'; \
|
export BACKEND_IMAGE_NAME='${BACKEND_IMAGE_NAME}'; \
|
||||||
@@ -140,18 +158,33 @@ jobs:
|
|||||||
export IMAGE_TAG='${IMAGE_TAG}'; \
|
export IMAGE_TAG='${IMAGE_TAG}'; \
|
||||||
export HARBOR_ENDPOINT='${HARBOR_ENDPOINT}'; \
|
export HARBOR_ENDPOINT='${HARBOR_ENDPOINT}'; \
|
||||||
export HARBOR_ROBOT_ACCOUNT='${HARBOR_ROBOT_ACCOUNT}'; \
|
export HARBOR_ROBOT_ACCOUNT='${HARBOR_ROBOT_ACCOUNT}'; \
|
||||||
set -e; \
|
|
||||||
cd \"\${DEPLOY_PATH}\"; \
|
cd \"\${DEPLOY_PATH}\"; \
|
||||||
docker login \"\${HARBOR_ENDPOINT}\" -u \"\${HARBOR_ROBOT_ACCOUNT}\" --password-stdin; \
|
docker login \"\${HARBOR_ENDPOINT}\" -u \"\${HARBOR_ROBOT_ACCOUNT}\" --password-stdin; \
|
||||||
set -a; \
|
set -a; . ./.env; set +a; \
|
||||||
. ./.env; \
|
|
||||||
set +a; \
|
# 네트워크 생성
|
||||||
for net in baron_net public_net ory-net hydranet kratosnet; do
|
for net in baron_net public_net ory-net hydranet kratosnet; do
|
||||||
docker network inspect "\$net" >/dev/null 2>&1 || docker network create "\$net"
|
docker network inspect \"\$net\" >/dev/null 2>&1 || docker network create \"\$net\"
|
||||||
done
|
done
|
||||||
# Assuming template usage similar to prod
|
|
||||||
envsubst < docker-compose.staging.template.yaml > docker-compose.yml; \
|
envsubst < docker-compose.staging.template.yaml > docker-compose.yml; \
|
||||||
# Pull & Up
|
|
||||||
# Assuming staging runs both infra, ory, and app stack
|
# [중요] 설정 파일 권한 문제 해결 (Ory 이미지는 root가 아닌 사용자로 실행됨)
|
||||||
|
chmod -R 777 docker/ory
|
||||||
|
|
||||||
docker compose -f compose.infra.yml -f compose.ory.yml -f docker-compose.yml pull; \
|
docker compose -f compose.infra.yml -f compose.ory.yml -f docker-compose.yml pull; \
|
||||||
docker compose -f compose.infra.yml -f compose.ory.yml -f docker-compose.yml up -d"
|
|
||||||
|
# [주의] DB 초기화 스크립트는 '새로운 볼륨'에서만 실행됨.
|
||||||
|
# DB 초기화 문제를 확실히 해결하기 위해 기존 볼륨을 날리고 다시 띄움 (데이터 삭제됨 주의)
|
||||||
|
# 스테이징이므로 초기화 진행. 데이터 보존이 필요하면 이 줄 제거하고 수동으로 DB 만들어야 함.
|
||||||
|
docker compose -f compose.infra.yml -f compose.ory.yml -f docker-compose.yml down -v || true
|
||||||
|
|
||||||
|
docker compose -f compose.infra.yml -f compose.ory.yml -f docker-compose.yml up -d --remove-orphans; \
|
||||||
|
|
||||||
|
# 배포 후 상태 확인 (실패 시 로그 출력을 위함)
|
||||||
|
sleep 10; \
|
||||||
|
if [ \$(docker inspect -f '{{.State.ExitCode}}' baron-sso-staging-kratos-migrate-1) -ne 0 ]; then \
|
||||||
|
echo 'Kratos Migrate Failed. Logs:'; \
|
||||||
|
docker logs baron-sso-staging-kratos-migrate-1; \
|
||||||
|
exit 1; \
|
||||||
|
fi"
|
||||||
@@ -31,7 +31,7 @@ services:
|
|||||||
- KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS='["${KRATOS_UI_URL:-http://localhost:5000}","${USERFRONT_URL:-http://localhost:5000}"]'
|
- KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS='["${KRATOS_UI_URL:-http://localhost:5000}","${USERFRONT_URL:-http://localhost:5000}"]'
|
||||||
volumes:
|
volumes:
|
||||||
- ./docker/ory/kratos:/etc/config/kratos
|
- ./docker/ory/kratos:/etc/config/kratos
|
||||||
command: migrate sql -c /etc/config/kratos/kratos.yml --yes
|
command: migrate sql up -e -c /etc/config/kratos/kratos.yml --yes
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres_ory:
|
postgres_ory:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -62,7 +62,7 @@ services:
|
|||||||
image: oryd/hydra:${HYDRA_VERSION:-v25.4.0}
|
image: oryd/hydra:${HYDRA_VERSION:-v25.4.0}
|
||||||
environment:
|
environment:
|
||||||
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20
|
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20
|
||||||
command: migrate sql -e --yes
|
command: migrate sql up -e --yes
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres_ory:
|
postgres_ory:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -74,10 +74,10 @@ services:
|
|||||||
container_name: ory_hydra
|
container_name: ory_hydra
|
||||||
environment:
|
environment:
|
||||||
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20
|
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20
|
||||||
- URLS_SELF_ISSUER="${USERFRONT_URL:-http://localhost:5000}/oidc"
|
- URLS_SELF_ISSUER=${USERFRONT_URL:-http://localhost:5000}/oidc
|
||||||
- URLS_LOGIN="${USERFRONT_URL:-http://localhost:5000}/login"
|
- URLS_LOGIN=${USERFRONT_URL:-http://localhost:5000}/login
|
||||||
- URLS_CONSENT="${USERFRONT_URL:-http://localhost:5000}/consent"
|
- URLS_CONSENT=${USERFRONT_URL:-http://localhost:5000}/consent
|
||||||
- SECRETS_SYSTEM="${ORY_POSTGRES_PASSWORD}"
|
- SECRETS_SYSTEM=${ORY_POSTGRES_PASSWORD}
|
||||||
volumes:
|
volumes:
|
||||||
- ./docker/ory/hydra:/etc/config/hydra
|
- ./docker/ory/hydra:/etc/config/hydra
|
||||||
command: serve -c /etc/config/hydra/hydra.yml all --dev
|
command: serve -c /etc/config/hydra/hydra.yml all --dev
|
||||||
@@ -88,6 +88,31 @@ services:
|
|||||||
- ory-net
|
- ory-net
|
||||||
- hydranet
|
- hydranet
|
||||||
|
|
||||||
|
# [수정됨] Oathkeeper 서비스 추가 (Backend 연결 문제 해결)
|
||||||
|
oathkeeper:
|
||||||
|
image: oryd/oathkeeper:${OATHKEEPER_VERSION:-v0.40.6}
|
||||||
|
container_name: oathkeeper
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
kratos:
|
||||||
|
condition: service_started
|
||||||
|
environment:
|
||||||
|
- LOG_LEVEL=debug
|
||||||
|
command: serve proxy --config /etc/config/oathkeeper/oathkeeper.yml
|
||||||
|
volumes:
|
||||||
|
- ./docker/ory/oathkeeper:/etc/config/oathkeeper
|
||||||
|
networks:
|
||||||
|
- ory-net
|
||||||
|
- baron_net # Backend가 통신하기 위해 필수
|
||||||
|
- public_net
|
||||||
|
ports:
|
||||||
|
- "4455:4455" # Proxy
|
||||||
|
- "4456:4456" # API (Backend 헬스체크용)
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:4456/health/ready"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
volumes:
|
volumes:
|
||||||
ory_postgres_data:
|
ory_postgres_data:
|
||||||
|
|
||||||
@@ -104,3 +129,7 @@ networks:
|
|||||||
public_net:
|
public_net:
|
||||||
external: true
|
external: true
|
||||||
name: public_net
|
name: public_net
|
||||||
|
# [수정됨] Baron Net 추가 정의 (Oathkeeper 연결용)
|
||||||
|
baron_net:
|
||||||
|
external: true
|
||||||
|
name: baron_net
|
||||||
@@ -2,41 +2,32 @@ name: baron-sso-staging
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
image: ${BACKEND_IMAGE_NAME}:${IMAGE_TAG}
|
image: ${BACKEND_IMAGE_NAME}:${IMAGE_TAG}
|
||||||
container_name: baron_backend
|
container_name: baron_backend
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
- APP_ENV=stage
|
- DB_HOST=baron_postgres
|
||||||
- GO_ENV=stage
|
- IDP_PROVIDER=ory
|
||||||
- COOKIE_SECRET="${COOKIE_SECRET}"
|
- OATHKEEPER_API_URL=http://oathkeeper:4456
|
||||||
- DB_HOST=postgres
|
- PROFILE_CACHE_TTL="${PROFILE_CACHE_TTL:-30m}"
|
||||||
- CLICKHOUSE_HOST=clickhouse
|
ports:
|
||||||
- CLICKHOUSE_PORT="${CLICKHOUSE_PORT_NATIVE:-9000}"
|
- "${BACKEND_PORT:-3000}:3000"
|
||||||
- CLICKHOUSE_USER="${CLICKHOUSE_USER:-baron}"
|
depends_on:
|
||||||
- CLICKHOUSE_PASSWORD="${CLICKHOUSE_PASSWORD:-password}"
|
oathkeeper:
|
||||||
- USERFRONT_URL="${USERFRONT_URL:-https://sso.hmac.kr}"
|
condition: service_healthy
|
||||||
- REDIS_ADDR="${REDIS_ADDR:-redis:6389}"
|
infra_check:
|
||||||
- IDP_PROVIDER=ory
|
condition: service_started
|
||||||
- KRATOS_ADMIN_URL="${KRATOS_ADMIN_URL:-http://ory_kratos:4434}"
|
networks:
|
||||||
- HYDRA_ADMIN_URL="${HYDRA_ADMIN_URL:-http://ory_hydra:4445}"
|
- baron_net
|
||||||
- HYDRA_PUBLIC_URL="${HYDRA_PUBLIC_URL:-http://ory_hydra:4444}"
|
- ory-net
|
||||||
- PROFILE_CACHE_TTL="${PROFILE_CACHE_TTL:-30m}"
|
healthcheck:
|
||||||
ports:
|
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
|
||||||
- "${BACKEND_PORT:-3000}:3000"
|
interval: 10s
|
||||||
depends_on:
|
timeout: 5s
|
||||||
infra_check:
|
retries: 10
|
||||||
condition: service_started
|
start_period: 60s
|
||||||
networks:
|
|
||||||
- baron_net
|
|
||||||
- ory-net
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 3
|
|
||||||
start_period: 10s
|
|
||||||
|
|
||||||
adminfront:
|
adminfront:
|
||||||
image: ${ADMINFRONT_IMAGE_NAME}:${IMAGE_TAG}
|
image: ${ADMINFRONT_IMAGE_NAME}:${IMAGE_TAG}
|
||||||
@@ -84,8 +75,8 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
command: >
|
command: >
|
||||||
/bin/sh -c "mkdir -p /usr/share/nginx/html/assets &&
|
/bin/sh -c "mkdir -p /usr/share/nginx/html/assets &&
|
||||||
echo \"BACKEND_URL=$${BACKEND_URL}\" >> /usr/share/nginx/html/assets/.env &&
|
echo \"BACKEND_URL=${BACKEND_URL}\" >> /usr/share/nginx/html/assets/.env &&
|
||||||
echo \"USERFRONT_URL=$${USERFRONT_URL}\" >> /usr/share/nginx/html/assets/.env &&
|
echo \"USERFRONT_URL=${USERFRONT_URL}\" >> /usr/share/nginx/html/assets/.env &&
|
||||||
echo \"APP_ENV=stage\" >> /usr/share/nginx/html/assets/.env &&
|
echo \"APP_ENV=stage\" >> /usr/share/nginx/html/assets/.env &&
|
||||||
cp /usr/share/nginx/html/assets/.env /usr/share/nginx/html/.env &&
|
cp /usr/share/nginx/html/assets/.env /usr/share/nginx/html/.env &&
|
||||||
nginx -g 'daemon off;'"
|
nginx -g 'daemon off;'"
|
||||||
@@ -93,8 +84,8 @@ services:
|
|||||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:5000/"]
|
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:5000/"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 3
|
retries: 5
|
||||||
start_period: 10s
|
start_period: 30s
|
||||||
|
|
||||||
infra_check:
|
infra_check:
|
||||||
image: alpine
|
image: alpine
|
||||||
|
|||||||
@@ -13,7 +13,11 @@ class AuthProxyService {
|
|||||||
return dotenv.env[key] ?? fallback;
|
return dotenv.env[key] ?? fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String get _baseUrl => _envOrDefault('BACKEND_URL', 'https://sso.hmac.kr');
|
static String get _baseUrl {
|
||||||
|
final rawUrl = _envOrDefault('BACKEND_URL', 'https://sso.hmac.kr');
|
||||||
|
// 배포 환경에서 $ 기호나 공백이 섞여 들어오는 경우를 방지하기 위해 정제합니다.
|
||||||
|
return rawUrl.replaceAll(r'$', '').trim().replaceAll(RegExp(r'/$'), '');
|
||||||
|
}
|
||||||
static bool get _isProd {
|
static bool get _isProd {
|
||||||
final env = _envOrDefault('APP_ENV', 'dev').toLowerCase();
|
final env = _envOrDefault('APP_ENV', 'dev').toLowerCase();
|
||||||
return env == 'prod' || env == 'production';
|
return env == 'prod' || env == 'production';
|
||||||
|
|||||||
Reference in New Issue
Block a user