forked from baron/baron-sso
145 lines
6.5 KiB
YAML
145 lines
6.5 KiB
YAML
name: Release Baron SSO to Production
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
rc_version_tag:
|
|
description: "The version tag to release to production (e.g., v1.2601.1-RC1)"
|
|
required: true
|
|
type: string
|
|
|
|
jobs:
|
|
release:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Login to Harbor Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ vars.HARBOR_ENDPOINT }}
|
|
username: ${{ vars.HARBOR_ROBOT_ACCOUNT }}
|
|
password: ${{ secrets.HARBOR_ROBOT_KEY }}
|
|
|
|
- name: Parse RC and re-tag to final
|
|
id: retag
|
|
env:
|
|
HARBOR_HOSTNAME: ${{ vars.HARBOR_HOSTNAME }}
|
|
HARBOR_USER: ${{ vars.HARBOR_ROBOT_ACCOUNT }}
|
|
HARBOR_PASSWORD: ${{ secrets.HARBOR_ROBOT_KEY }}
|
|
run: |
|
|
BASE_TAG=$(echo "${{ github.event.inputs.rc_version_tag }}" | xargs)
|
|
|
|
if [[ ! "$BASE_TAG" =~ ^v[0-9]+\.[0-9]{4}\.[0-9]+-RC[0-9]+$ ]]; then
|
|
echo "::error::rc_version_tag must look like vX.YYMM.Z-RC## (got: $BASE_TAG)"
|
|
exit 1
|
|
fi
|
|
RE_TAG="${BASE_TAG%-RC*}"
|
|
echo "Final tag will be: ${RE_TAG}"
|
|
|
|
if ! command -v skopeo >/dev/null 2>&1; then
|
|
sudo apt-get update -y && sudo apt-get install -y skopeo
|
|
fi
|
|
|
|
# Re-tag backend image
|
|
echo "Re-tagging backend image..."
|
|
skopeo copy --preserve-digests \
|
|
--src-creds "${HARBOR_USER}:${HARBOR_PASSWORD}" --dest-creds "${HARBOR_USER}:${HARBOR_PASSWORD}" \
|
|
--src-tls-verify=false --dest-tls-verify=false \
|
|
"docker://${HARBOR_HOSTNAME}/baron_sso/backend:${BASE_TAG}" "docker://${HARBOR_HOSTNAME}/baron_sso/backend:${RE_TAG}"
|
|
|
|
# Re-tag userfront image
|
|
echo "Re-tagging userfront image..."
|
|
skopeo copy --preserve-digests \
|
|
--src-creds "${HARBOR_USER}:${HARBOR_PASSWORD}" --dest-creds "${HARBOR_USER}:${HARBOR_PASSWORD}" \
|
|
--src-tls-verify=false --dest-tls-verify=false \
|
|
"docker://${HARBOR_HOSTNAME}/baron_sso/userfront:${BASE_TAG}" "docker://${HARBOR_HOSTNAME}/baron_sso/userfront:${RE_TAG}"
|
|
|
|
echo "final_image_tag=${RE_TAG}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Setup SSH
|
|
uses: webfactory/ssh-agent@v0.9.0
|
|
with:
|
|
ssh-private-key: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
|
|
|
|
- name: Deploy to Production
|
|
env:
|
|
IMAGE_TAG: ${{ steps.retag.outputs.final_image_tag }}
|
|
BACKEND_IMAGE_NAME: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/backend
|
|
USERFRONT_IMAGE_NAME: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/userfront
|
|
DEPLOY_PATH: ${{ vars.PROD_DEPLOY_PATH }}
|
|
PROD_HOST: ${{ vars.PROD_HOST }}
|
|
PROD_USER: ${{ vars.PROD_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: PROD_USER='${PROD_USER}'"
|
|
echo "DEBUG: PROD_HOST='${PROD_HOST}'"
|
|
echo "DEBUG: DEPLOY_PATH='${DEPLOY_PATH}'"
|
|
|
|
# Sanity check (fail fast with a clear message)
|
|
if [ -z "${PROD_USER}" ] || [ -z "${PROD_HOST}" ] || [ -z "${DEPLOY_PATH}" ]; then
|
|
echo "::error::Missing required vars (PROD_USER/PROD_HOST/DEPLOY_PATH). Check Gitea repo variables."
|
|
exit 1
|
|
fi
|
|
|
|
ssh-keyscan -H "${PROD_HOST}" >> ~/.ssh/known_hosts
|
|
|
|
ssh "${PROD_USER}@${PROD_HOST}" "mkdir -p '${DEPLOY_PATH}'"
|
|
|
|
# Create the main .env file for Baron SSO on the remote server
|
|
# Note: All values are pulled from Gitea secrets and variables
|
|
printf '%s\n' \
|
|
"APP_ENV=production" \
|
|
"TZ=Asia/Seoul" \
|
|
"DB_PORT=${{ vars.PROD_DB_PORT }}" \
|
|
"CLICKHOUSE_PORT_HTTP=${{ vars.PROD_CLICKHOUSE_PORT_HTTP }}" \
|
|
"CLICKHOUSE_PORT_NATIVE=${{ vars.PROD_CLICKHOUSE_PORT_NATIVE }}" \
|
|
"CLICKHOUSE_USER=${{ vars.PROD_CLICKHOUSE_USER }}" \
|
|
"CLICKHOUSE_PASSWORD=${{ secrets.PROD_CLICKHOUSE_PASSWORD }}" \
|
|
"BACKEND_PORT=${{ vars.PROD_BACKEND_PORT }}" \
|
|
"USERFRONT_PORT=${{ vars.PROD_USERFRONT_PORT }}" \
|
|
"DB_USER=${{ vars.PROD_DB_USER }}" \
|
|
"DB_PASSWORD=${{ secrets.PROD_DB_PASSWORD }}" \
|
|
"DB_NAME=${{ vars.PROD_DB_NAME }}" \
|
|
"COOKIE_SECRET=${{ secrets.PROD_COOKIE_SECRET }}" \
|
|
"JWT_SECRET=${{ secrets.PROD_JWT_SECRET }}" \
|
|
"REDIS_ADDR=${{ vars.PROD_REDIS_ADDR }}" \
|
|
"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 }}" \
|
|
"USERFRONT_URL=${{ vars.PROD_USERFRONT_URL }}" \
|
|
"BACKEND_URL=${{ vars.PROD_BACKEND_URL }}" \
|
|
> .env
|
|
|
|
# Copy compose template and .env file to the remote server
|
|
scp docker/docker-compose.template.yaml .env "${PROD_USER}@${PROD_HOST}:${DEPLOY_PATH}/"
|
|
scp docker/compose.infra.prd.yaml "${PROD_USER}@${PROD_HOST}:${DEPLOY_PATH}/compose.infra.yml"
|
|
|
|
# Deploy Baron SSO
|
|
echo "${HARBOR_ROBOT_KEY}" | ssh "${PROD_USER}@${PROD_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; \
|
|
envsubst < docker-compose.template.yaml > docker-compose.yml; \
|
|
docker compose -f compose.infra.yml -f docker-compose.yml pull; \
|
|
docker compose -f compose.infra.yml -f docker-compose.yml up -d --remove-orphans"
|