Files
taxbaik/.gitea/workflows/deploy.yml
T
kjh2064 f29f2c3cff
TaxBaik Browser E2E / browser-e2e (push) Failing after 1m3s
TaxBaik CI/CD / build-and-deploy (push) Failing after 2m46s
개선: 배포 검증과 관리자 UX 안정화
2026-06-27 20:57:09 +09:00

177 lines
7.8 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 }}"
if [ -z "$JWT_SECRET_KEY" ]; then
echo "Missing TAXBAIK_JWT_SECRET_KEY secret" >&2
exit 1
fi
JWT_SECRET_KEY="$JWT_SECRET_KEY" python3 - <<'PY'
import json
import os
from pathlib import Path
config = {
"Jwt": {
"SecretKey": os.environ["JWT_SECRET_KEY"]
}
}
Path("./publish/appsettings.Production.json").write_text(
json.dumps(config, ensure_ascii=False, indent=2),
encoding="utf-8",
)
PY
- 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