forked from baron/baron-sso
Merge pull request 'feat/staging-deploy' (#214) from feat/staging-deploy into main
Reviewed-on: ai-team/baron-sso#214
This commit is contained in:
@@ -86,6 +86,26 @@ jobs:
|
||||
provenance: false
|
||||
sbom: false
|
||||
|
||||
- name: Build and push adminfront RC image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./adminfront
|
||||
file: ./adminfront/Dockerfile
|
||||
push: true
|
||||
tags: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/adminfront:${{ steps.rc_calculator.outputs.new_rc_tag }}
|
||||
provenance: false
|
||||
sbom: false
|
||||
|
||||
- name: Build and push devfront RC image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./devfront
|
||||
file: ./devfront/Dockerfile
|
||||
push: true
|
||||
tags: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/devfront:${{ steps.rc_calculator.outputs.new_rc_tag }}
|
||||
provenance: false
|
||||
sbom: false
|
||||
|
||||
- name: Temporarily update userfront nginx port
|
||||
run: |
|
||||
sed -i 's/listen 5000;/listen 80;/g' userfront/nginx.conf
|
||||
|
||||
153
.gitea/workflows/staging_release.yml
Normal file
153
.gitea/workflows/staging_release.yml
Normal file
@@ -0,0 +1,153 @@
|
||||
name: Release Baron SSO to Staging
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
rc_version_tag:
|
||||
description: "The version tag to deploy to staging (e.g., v1.2601.1-RC1)"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
deploy-staging:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup SSH
|
||||
uses: webfactory/ssh-agent@v0.9.0
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.STAGE_SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Deploy to Staging
|
||||
env:
|
||||
IMAGE_TAG: ${{ github.event.inputs.rc_version_tag }}
|
||||
BACKEND_IMAGE_NAME: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/backend
|
||||
USERFRONT_IMAGE_NAME: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/userfront
|
||||
# Staging-specific variables (STAGE_*)
|
||||
DEPLOY_PATH: ${{ vars.STAGE_DEPLOY_PATH }}
|
||||
STAGE_HOST: ${{ vars.STAGE_HOST }}
|
||||
STAGE_USER: ${{ vars.STAGE_USER }}
|
||||
HARBOR_ENDPOINT: ${{ vars.HARBOR_ENDPOINT }}
|
||||
HARBOR_ROBOT_ACCOUNT: ${{ vars.HARBOR_ROBOT_ACCOUNT }}
|
||||
HARBOR_ROBOT_KEY: ${{ secrets.HARBOR_ROBOT_KEY }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
echo "DEBUG: STAGE_USER='${STAGE_USER}'"
|
||||
echo "DEBUG: STAGE_HOST='${STAGE_HOST}'"
|
||||
echo "DEBUG: DEPLOY_PATH='${DEPLOY_PATH}'"
|
||||
|
||||
# Sanity check
|
||||
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."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ssh-keyscan -H "${STAGE_HOST}" >> ~/.ssh/known_hosts
|
||||
|
||||
ssh "${STAGE_USER}@${STAGE_HOST}" "mkdir -p '${DEPLOY_PATH}'"
|
||||
|
||||
# Create .env for Staging
|
||||
# Mapped from Gitea secrets/vars to .env.sample structure
|
||||
# Note: Common vars like DB_PORT do not have STAGE_ prefix in Gitea settings based on user input.
|
||||
# Secrets have STG_ prefix.
|
||||
printf '%s\n' \
|
||||
"APP_ENV=stage" \
|
||||
"TZ=Asia/Seoul" \
|
||||
"IDP_PROVIDER=ory" \
|
||||
"DB_PORT=${{ vars.DB_PORT }}" \
|
||||
"CLICKHOUSE_PORT_HTTP=${{ vars.CLICKHOUSE_PORT_HTTP }}" \
|
||||
"CLICKHOUSE_PORT_NATIVE=${{ vars.CLICKHOUSE_PORT_NATIVE }}" \
|
||||
"BACKEND_PORT=${{ vars.BACKEND_PORT }}" \
|
||||
"ADMINFRONT_PORT=${{ vars.ADMINFRONT_PORT }}" \
|
||||
"DEVFRONT_PORT=${{ vars.DEVFRONT_PORT }}" \
|
||||
"USERFRONT_PORT=${{ vars.USERFRONT_PORT }}" \
|
||||
"DB_USER=${{ vars.DB_USER }}" \
|
||||
"DB_PASSWORD=${{ secrets.STG_DB_PASSWORD }}" \
|
||||
"DB_NAME=${{ vars.DB_NAME }}" \
|
||||
"COOKIE_SECRET=${{ secrets.STG_COOKIE_SECRET }}" \
|
||||
"JWT_SECRET=${{ secrets.STG_JWT_SECRET }}" \
|
||||
"REDIS_ADDR=${{ vars.REDIS_ADDR }}" \
|
||||
"CORS_ALLOWED_ORIGINS=${{ vars.CORS_ALLOWED_ORIGINS }}" \
|
||||
"AUDIT_WORKER_COUNT=5" \
|
||||
"AUDIT_QUEUE_SIZE=2000" \
|
||||
"PROFILE_CACHE_TTL=${{ vars.PROFILE_CACHE_TTL }}" \
|
||||
"DESCOPE_PROJECT_ID=${{ vars.DESCOPE_PROJECT_ID }}" \
|
||||
"DESCOPE_MANAGEMENT_KEY=${{ secrets.DESCOPE_MANAGEMENT_KEY }}" \
|
||||
"DESCOPE_TEST_ACCOUNT=${{ vars.DESCOPE_TEST_ACCOUNT }}" \
|
||||
"NAVER_CLOUD_ACCESS_KEY=${{ vars.NAVER_CLOUD_ACCESS_KEY }}" \
|
||||
"NAVER_CLOUD_SECRET_KEY=${{ secrets.NAVER_CLOUD_SECRET_KEY }}" \
|
||||
"NAVER_CLOUD_SERVICE_ID=${{ vars.NAVER_CLOUD_SERVICE_ID }}" \
|
||||
"NAVER_SENDER_PHONE_NUMBER=${{ vars.NAVER_SENDER_PHONE_NUMBER }}" \
|
||||
"AWS_REGION=${{ vars.AWS_REGION }}" \
|
||||
"AWS_ACCESS_KEY_ID=${{ vars.AWS_ACCESS_KEY_ID }}" \
|
||||
"AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}" \
|
||||
"AWS_SES_SENDER=${{ vars.AWS_SES_SENDER }}" \
|
||||
"ADMIN_EMAIL=${{ vars.ADMIN_EMAIL }}" \
|
||||
"ADMIN_PASSWORD=${{ secrets.STG_ADMIN_PASSWORD }}" \
|
||||
"USERFRONT_URL=${{ vars.USERFRONT_URL }}" \
|
||||
"BACKEND_URL=${{ vars.BACKEND_URL }}" \
|
||||
"OATHKEEPER_PUBLIC_URL=${{ vars.OATHKEEPER_PUBLIC_URL }}" \
|
||||
"ORY_POSTGRES_TAG=${{ vars.ORY_POSTGRES_TAG }}" \
|
||||
"ORY_POSTGRES_USER=${{ vars.ORY_POSTGRES_USER }}" \
|
||||
"ORY_POSTGRES_PASSWORD=${{ secrets.STG_ORY_POSTGRES_PASSWORD }}" \
|
||||
"ORY_POSTGRES_DB=${{ vars.ORY_POSTGRES_DB }}" \
|
||||
"KRATOS_DB=${{ vars.KRATOS_DB }}" \
|
||||
"HYDRA_DB=${{ vars.HYDRA_DB }}" \
|
||||
"KETO_DB=${{ vars.KETO_DB }}" \
|
||||
"KRATOS_VERSION=${{ vars.KRATOS_VERSION }}" \
|
||||
"KRATOS_UI_NODE_VERSION=${{ vars.KRATOS_UI_NODE_VERSION }}" \
|
||||
"HYDRA_VERSION=${{ vars.HYDRA_VERSION }}" \
|
||||
"KETO_VERSION=${{ vars.KETO_VERSION }}" \
|
||||
"ORY_SDK_URL=${{ vars.ORY_SDK_URL }}" \
|
||||
"KRATOS_PUBLIC_URL=${{ vars.KRATOS_PUBLIC_URL }}" \
|
||||
"KRATOS_ADMIN_URL=${{ vars.KRATOS_ADMIN_URL }}" \
|
||||
"KRATOS_BROWSER_URL=${{ vars.KRATOS_BROWSER_URL }}" \
|
||||
"KRATOS_UI_URL=${{ vars.KRATOS_UI_URL }}" \
|
||||
"HYDRA_ADMIN_URL=${{ vars.HYDRA_ADMIN_URL }}" \
|
||||
"HYDRA_PUBLIC_URL=${{ vars.HYDRA_PUBLIC_URL }}" \
|
||||
"JWKS_URL=${{ vars.JWKS_URL }}" \
|
||||
"OATHKEEPER_VERSION=${{ vars.OATHKEEPER_VERSION }}" \
|
||||
"OATHKEEPER_UID=${{ vars.OATHKEEPER_UID }}" \
|
||||
"OATHKEEPER_GID=${{ vars.OATHKEEPER_GID }}" \
|
||||
"OATHKEEPER_HEALTH_URL=${{ vars.OATHKEEPER_HEALTH_URL }}" \
|
||||
"OATHKEEPER_HEALTH_INTERVAL_SECONDS=${{ vars.OATHKEEPER_HEALTH_INTERVAL_SECONDS }}" \
|
||||
"OATHKEEPER_HEALTH_TIMEOUT_SECONDS=${{ vars.OATHKEEPER_HEALTH_TIMEOUT_SECONDS }}" \
|
||||
"OATHKEEPER_HEALTH_ENABLED=${{ vars.OATHKEEPER_HEALTH_ENABLED }}" \
|
||||
"CSRF_COOKIE_NAME=${{ vars.CSRF_COOKIE_NAME }}" \
|
||||
"CSRF_COOKIE_SECRET=${{ secrets.STG_CSRF_COOKIE_SECRET }}" \
|
||||
"OATHKEEPER_INTROSPECT_CLIENT_ID=${{ vars.OATHKEEPER_INTROSPECT_CLIENT_ID }}" \
|
||||
"OATHKEEPER_INTROSPECT_CLIENT_SECRET=${{ secrets.STG_OATHKEEPER_INTROSPECT_CLIENT_SECRET }}" \
|
||||
> .env
|
||||
|
||||
# Copy artifacts to remote
|
||||
# Using compose.infra.yaml as base for staging (assuming simplified structure compared to prod)
|
||||
# OR use docker-compose.template.yaml if staging follows prod structure strictly
|
||||
scp docker/docker-compose.template.yaml .env "${STAGE_USER}@${STAGE_HOST}:${DEPLOY_PATH}/"
|
||||
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/"
|
||||
|
||||
# Deploy
|
||||
echo "${HARBOR_ROBOT_KEY}" | ssh "${STAGE_USER}@${STAGE_HOST}" \
|
||||
"export DEPLOY_PATH='${DEPLOY_PATH}'; \
|
||||
export BACKEND_IMAGE_NAME='${BACKEND_IMAGE_NAME}'; \
|
||||
export USERFRONT_IMAGE_NAME='${USERFRONT_IMAGE_NAME}'; \
|
||||
export IMAGE_TAG='${IMAGE_TAG}'; \
|
||||
export HARBOR_ENDPOINT='${HARBOR_ENDPOINT}'; \
|
||||
export HARBOR_ROBOT_ACCOUNT='${HARBOR_ROBOT_ACCOUNT}'; \
|
||||
set -e; \
|
||||
cd \"\${DEPLOY_PATH}\"; \
|
||||
docker login \"\${HARBOR_ENDPOINT}\" -u \"\${HARBOR_ROBOT_ACCOUNT}\" --password-stdin; \
|
||||
set -a; \
|
||||
. ./.env; \
|
||||
set +a; \
|
||||
# Assuming template usage similar to prod
|
||||
envsubst < docker-compose.template.yaml > docker-compose.yml; \
|
||||
# Pull & Up
|
||||
# Assuming staging runs both infra, ory, and app stack
|
||||
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 --remove-orphans"
|
||||
@@ -58,6 +58,14 @@ func (m *MockTenantService) GetTenantBySlug(ctx context.Context, slug string) (*
|
||||
return args.Get(0).(*domain.Tenant), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockTenantService) GetTenant(ctx context.Context, id string) (*domain.Tenant, error) {
|
||||
args := m.Called(ctx, id)
|
||||
if args.Get(0) == nil {
|
||||
return nil, args.Error(1)
|
||||
}
|
||||
return args.Get(0).(*domain.Tenant), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockTenantService) SetKetoService(keto service.KetoService) {
|
||||
m.Called(keto)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user