name: deploy on: push: branches: - main workflow_dispatch: permissions: contents: write jobs: deploy: if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/main') runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' - uses: pnpm/action-setup@v4 with: version: 10 - uses: actions/setup-node@v4 with: node-version: 22 cache: pnpm cache-dependency-path: frontend/pnpm-lock.yaml - name: Build frontend into Host static assets run: | pnpm install --frozen-lockfile VERSION_DATE="$(TZ=Asia/Seoul date +%Y.%m.%d)" RELEASE_COUNT="$(git ls-remote --tags origin "refs/tags/v${VERSION_DATE}.*" | wc -l | tr -d ' ')" VERSION_SEQUENCE="$((RELEASE_COUNT + 1))" APP_VERSION="${VERSION_DATE}.${VERSION_SEQUENCE}.${GITHUB_SHA::10}" echo "VITE_APP_VERSION=${APP_VERSION}" >> "$GITHUB_ENV" echo "release_version=${APP_VERSION}" VITE_APP_VERSION="${APP_VERSION}" pnpm build grep -R -q 'app-version' dist grep -R -q 'UI contract 4.0' dist grep -R -q "${APP_VERSION}" dist find ../src/KArtSell.Host/wwwroot -mindepth 1 -delete cp -R dist/. ../src/KArtSell.Host/wwwroot/ working-directory: frontend - run: dotnet restore KArtSell.sln - run: dotnet build KArtSell.sln --no-restore -c Release - name: Publish Release Build run: | dotnet publish -c Release -o ./publish src/KArtSell.Host dotnet publish -c Release -o ./publish src/KArtSell.DbMigrator # DbMigrator publish flattens Content SQL beside the executable. # Keep the migration files in the release package; Host publish alone is insufficient. test -f ./publish/0032_shadow_run_queued_status_contract.sql - name: Create deployment package run: | cd ./publish zip -r ../kartsell-release.zip . cd .. ls -lh kartsell-release.zip - name: Deploy via SCP to server env: DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} run: | # SSH 키 설정 (SSH_KEY에서 변환) echo "$DEPLOY_KEY" > /tmp/deploy_key.pem chmod 600 /tmp/deploy_key.pem # 서버에 파일 전송 echo "📦 Deploying kartsell-release.zip to server..." scp -i /tmp/deploy_key.pem -o StrictHostKeyChecking=no \ ./kartsell-release.zip kjh2064@178.104.200.7:/tmp/ echo "✅ File transferred" echo "" ssh -i /tmp/deploy_key.pem -o StrictHostKeyChecking=no kjh2064@178.104.200.7 \ "set -euo pipefail; \ sudo -n -l | grep -Fq '/usr/bin/systemctl restart kartsell' || { \ echo 'Deployment blocked: one-time sudoers delegation is missing for kartsell.' >&2; \ echo 'Expected: kjh2064 ALL=(root) NOPASSWD: /usr/bin/systemctl restart kartsell' >&2; \ exit 77; \ }; \ export KARTSELL_POSTGRES='${{ secrets.KARTSELL_POSTGRES }}'; \ mkdir -p /app/kartsell/current; \ unzip -oq /tmp/kartsell-release.zip -d /app/kartsell/current; \ cd /app/kartsell/current; \ test -f KArtSell.DbMigrator.dll; \ test -f 0032_shadow_run_queued_status_contract.sql; \ dotnet KArtSell.DbMigrator.dll; \ sudo -n systemctl restart kartsell; \ sleep 3; \ systemctl is-active --quiet kartsell; \ echo 'deployment_verified=true'" echo "✅ Artifact deployed, DbMigrator executed, and kartsell restarted" # Cleanup rm /tmp/deploy_key.pem - name: Tag release version run: | git tag "v${VITE_APP_VERSION}" git push origin "v${VITE_APP_VERSION}" notify: if: always() needs: deploy runs-on: ubuntu-latest steps: - name: Notify deployment status env: TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }} TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} run: | STATUS="${{ needs.deploy.result }}" if [ "$STATUS" = "success" ]; then MESSAGE="✅ K-ArtSell Aegis deployed successfully to production" else MESSAGE="❌ K-ArtSell Aegis deployment failed" fi curl -X POST "https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage" \ -d "chat_id=$TELEGRAM_CHAT_ID" \ -d "text=$MESSAGE" \ -d "parse_mode=HTML" || echo "Telegram notification failed"