Files
taxbaik/.gitea/workflows/deploy.yml
T
kjh2064 301efb32ff
TaxBaik CI/CD / build-and-deploy (push) Failing after 44s
TaxBaik Browser E2E / browser-e2e (push) Failing after 10m30s
fix: 텔레그램 알림 운영 설정 배포
2026-06-27 22:12:08 +09:00

173 lines
8.3 KiB
YAML

name: TaxBaik CI/CD
on:
push:
branches:
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0'
- name: Restore dependencies
run: dotnet restore TaxBaik.sln
- name: Build solution
run: |
dotnet clean TaxBaik.sln -c Release
dotnet build TaxBaik.sln -c Release --no-restore
- name: Test solution
run: dotnet test TaxBaik.sln -c Release --no-build
- name: Publish Web (통합 앱)
run: dotnet publish TaxBaik.Web/ -c Release -o ./publish --no-restore
- name: Write production secrets
run: |
set -e
JWT_SECRET_KEY="${{ secrets.TAXBAIK_JWT_SECRET_KEY }}"
TELEGRAM_BOT_TOKEN="${{ secrets.TAXBAIK_TELEGRAM_BOT_TOKEN }}"
TELEGRAM_CHAT_ID="${{ secrets.TAXBAIK_TELEGRAM_CHAT_ID }}"
if [ -z "$JWT_SECRET_KEY" ]; then
echo "Missing TAXBAIK_JWT_SECRET_KEY secret" >&2
exit 1
fi
if [ -z "$TELEGRAM_BOT_TOKEN" ]; then
echo "Missing TAXBAIK_TELEGRAM_BOT_TOKEN secret" >&2
exit 1
fi
if [ -z "$TELEGRAM_CHAT_ID" ]; then
echo "Missing TAXBAIK_TELEGRAM_CHAT_ID secret" >&2
exit 1
fi
JWT_SECRET_KEY="$JWT_SECRET_KEY" TELEGRAM_BOT_TOKEN="$TELEGRAM_BOT_TOKEN" TELEGRAM_CHAT_ID="$TELEGRAM_CHAT_ID" python3 -c 'import json, os, pathlib; pathlib.Path("./publish/appsettings.Production.json").write_text(json.dumps({"Jwt":{"SecretKey":os.environ["JWT_SECRET_KEY"]},"Telegram":{"BotToken":os.environ["TELEGRAM_BOT_TOKEN"],"ChatId":os.environ["TELEGRAM_CHAT_ID"]}}, ensure_ascii=False, indent=2), encoding="utf-8")'
test -s ./publish/appsettings.Production.json
- name: Copy migrations to publish
run: |
cp -r db/migrations ./publish/migrations || true
- name: Generate build info
run: |
mkdir -p ./publish/wwwroot
COMMIT_HASH=$(git rev-parse --short HEAD)
BUILD_TIME=$(date -u +'%Y-%m-%d %H:%M:%S UTC')
echo "Version: $COMMIT_HASH" > ./publish/wwwroot/version.txt
echo "Built: $BUILD_TIME" >> ./publish/wwwroot/version.txt
echo "✓ Version: $COMMIT_HASH"
- name: Deploy (CI only, 통합 Web)
run: |
set -e
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DEPLOY_HOME="/home/kjh2064"
DEPLOY_DIR="$DEPLOY_HOME/deployments/taxbaik_${TIMESTAMP}"
DEPLOY_HOST="${{ secrets.DEPLOY_HOST }}"
DEPLOY_USER="${{ secrets.DEPLOY_USER }}"
echo "=== Deploying TaxBaik v$(git rev-parse --short HEAD) ==="
mkdir -p ~/.ssh
SSH_KEY_B64="${{ secrets.DEPLOY_SSH_KEY_B64 }}"
SSH_KEY_RAW="${{ secrets.DEPLOY_SSH_KEY }}"
if [ -n "$SSH_KEY_B64" ]; then
printf '%s' "$SSH_KEY_B64" | base64 -d > ~/.ssh/id_ed25519
elif [ -n "$SSH_KEY_RAW" ]; then
if printf '%s' "$SSH_KEY_RAW" | grep -q 'BEGIN .*PRIVATE KEY'; then
printf '%b\n' "$SSH_KEY_RAW" > ~/.ssh/id_ed25519
else
printf '%s' "$SSH_KEY_RAW" | base64 -d > ~/.ssh/id_ed25519
fi
else
echo "Missing DEPLOY_SSH_KEY_B64 or DEPLOY_SSH_KEY secret" >&2
exit 1
fi
sed -i 's/\r$//' ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null || true
tar -czf taxbaik_publish.tgz -C ./publish .
scp -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes taxbaik_publish.tgz "$DEPLOY_USER@$DEPLOY_HOST:/tmp/taxbaik_publish_${TIMESTAMP}.tgz"
ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes "$DEPLOY_USER@$DEPLOY_HOST" "
set -e
mkdir -p '$DEPLOY_DIR'
tar -xzf '/tmp/taxbaik_publish_${TIMESTAMP}.tgz' -C '$DEPLOY_DIR'
rm -f '/tmp/taxbaik_publish_${TIMESTAMP}.tgz'
ln -sfn '$DEPLOY_DIR' '$DEPLOY_HOME/taxbaik_active'
sudo systemctl restart taxbaik
"
sleep 5
echo "✓ Deployed to $DEPLOY_HOST:$DEPLOY_DIR"
- name: Verify deployment
run: |
set -e
DEPLOY_HOST="${{ secrets.DEPLOY_HOST }}"
DEPLOY_USER="${{ secrets.DEPLOY_USER }}"
mkdir -p ~/.ssh
SSH_KEY_B64="${{ secrets.DEPLOY_SSH_KEY_B64 }}"
SSH_KEY_RAW="${{ secrets.DEPLOY_SSH_KEY }}"
if [ -n "$SSH_KEY_B64" ]; then
printf '%s' "$SSH_KEY_B64" | base64 -d > ~/.ssh/id_ed25519
elif [ -n "$SSH_KEY_RAW" ]; then
if printf '%s' "$SSH_KEY_RAW" | grep -q 'BEGIN .*PRIVATE KEY'; then
printf '%b\n' "$SSH_KEY_RAW" > ~/.ssh/id_ed25519
else
printf '%s' "$SSH_KEY_RAW" | base64 -d > ~/.ssh/id_ed25519
fi
else
echo "Missing DEPLOY_SSH_KEY_B64 or DEPLOY_SSH_KEY secret" >&2
exit 1
fi
sed -i 's/\r$//' ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null || true
ADMIN_TEST_PASSWORD="${{ secrets.TAXBAIK_ADMIN_TEST_PASSWORD }}"
HOME_STATUS="000"
LOGIN_STATUS="000"
BLOG_STATUS="000"
BLOG_HEADERS=""
BLOG_BODY=""
BLOG_FINAL_URL=""
AUTH_BODY=""
for i in $(seq 1 12); do
HOME_STATUS=$(ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes "$DEPLOY_USER@$DEPLOY_HOST" "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:5001/taxbaik/" || echo "000")
LOGIN_STATUS=$(ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes "$DEPLOY_USER@$DEPLOY_HOST" "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:5001/taxbaik/admin/login" || echo "000")
BLOG_STATUS_AND_URL=$(ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes "$DEPLOY_USER@$DEPLOY_HOST" "curl -s -L -D /tmp/taxbaik_blog_check.headers -o /tmp/taxbaik_blog_check.html -w '%{http_code} %{url_effective}' http://127.0.0.1:5001/taxbaik/blog/accountant-mistakes-5" || echo "000")
BLOG_STATUS=$(printf '%s' "$BLOG_STATUS_AND_URL" | awk '{print $1}')
BLOG_FINAL_URL=$(printf '%s' "$BLOG_STATUS_AND_URL" | awk '{print $2}')
BLOG_HEADERS=$(ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes "$DEPLOY_USER@$DEPLOY_HOST" "sed -n '1,12p' /tmp/taxbaik_blog_check.headers | tr '\n' ' '" || echo "")
BLOG_BODY=$(ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes "$DEPLOY_USER@$DEPLOY_HOST" "sed -n '1,12p' /tmp/taxbaik_blog_check.html | tr '\n' ' '" || echo "")
if [ "$HOME_STATUS" = "200" ] && [ "$LOGIN_STATUS" = "200" ] && [ "$BLOG_STATUS" = "200" ]; then
AUTH_BODY=$(ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes "$DEPLOY_USER@$DEPLOY_HOST" "python3 -c \"import json, urllib.request; req = urllib.request.Request('http://127.0.0.1:5001/taxbaik/api/auth/login', data=json.dumps({'username':'admin','password':'${ADMIN_TEST_PASSWORD}'}).encode(), headers={'Content-Type':'application/json'}, method='POST'); print(urllib.request.urlopen(req, timeout=20).read().decode())\"" || echo "")
if echo "$AUTH_BODY" | grep -q '"token"'; then
echo "Home Status: $HOME_STATUS"
echo "Login Status: $LOGIN_STATUS"
echo "Blog Status: $BLOG_STATUS"
echo "Auth Body: $AUTH_BODY"
echo "✓ Service is running"
exit 0
fi
fi
sleep 5
done
echo "Home Status: $HOME_STATUS"
echo "Login Status: $LOGIN_STATUS"
echo "Blog Status: $BLOG_STATUS"
echo "Blog Final URL: $BLOG_FINAL_URL"
echo "Blog Headers: $BLOG_HEADERS"
echo "Blog Body: $BLOG_BODY"
echo "Auth Body: $AUTH_BODY"
echo "Service verification failed; collecting remote service diagnostics..." >&2
ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes "$DEPLOY_USER@$DEPLOY_HOST" "systemctl is-active taxbaik; systemctl status taxbaik --no-pager -l | sed -n '1,120p'; journalctl -u taxbaik --no-pager -n 120" || true
exit 1