name: Deploy to Server on: push: branches: [ main ] workflow_dispatch: jobs: deploy: runs-on: - ubuntu-latest - self-hosted steps: - name: Prepare workspace run: | rm -rf /tmp/volunteer-deploy && mkdir -p /tmp/volunteer-deploy && cd /tmp/volunteer-deploy - name: Checkout (git) working-directory: /tmp/volunteer-deploy run: | if [ -d src ]; then rm -rf src; fi mkdir src && cd src git clone --depth 1 -b main https://gitea.fse-media.group/Henry_Du/VolunteerManage-for-byw.git . - name: Configure npm mirror working-directory: /tmp/volunteer-deploy/src run: | echo "registry=https://registry.npmmirror.com" > ~/.npmrc npm config set registry https://registry.npmmirror.com - name: Build client (native) working-directory: /tmp/volunteer-deploy/src/client run: | npm install --no-audit --no-fund npm run build - name: Build server (native) working-directory: /tmp/volunteer-deploy/src/server run: | npm install --no-audit --no-fund npm run build - name: Install server production deps working-directory: /tmp/volunteer-deploy/src/server run: | rm -rf node_modules npm install --omit=dev --no-audit --no-fund - name: Prepare deploy package working-directory: /tmp/volunteer-deploy run: | rm -rf deploy-pkg && mkdir -p deploy-pkg/app cp -r src/client/dist deploy-pkg/app/client/dist cp -r src/server/dist deploy-pkg/app/server/dist cp -r src/server/node_modules deploy-pkg/app/server/node_modules mkdir -p deploy-pkg/app/server/src/db cp src/server/src/db/schema.sql deploy-pkg/app/server/src/db/schema.sql cat > deploy-pkg/docker-compose.yml <<'EOF' services: volunteer: image: node:20-alpine container_name: volunteer-manage restart: unless-stopped working_dir: /app/server command: ["node", "dist/index.js"] ports: - "3000:3000" environment: - NODE_ENV=production - PORT=3000 - JWT_SECRET=${JWT_SECRET:-volunteer-manage-secret-key-2026} volumes: - /opt/volunteer/data:/app/server/data - /opt/volunteer/app:/app:ro EOF - name: Prepare SSH key env: SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} run: | mkdir -p ~/.ssh && chmod 700 ~/.ssh rm -f ~/.ssh/deploy_key ~/.ssh/known_hosts printf '%s\n' "$SSH_PRIVATE_KEY" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key printf 'Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n IdentityFile ~/.ssh/deploy_key\n' > ~/.ssh/config chmod 600 ~/.ssh/config - name: Deploy via SSH env: SSH_HOST: ${{ secrets.SSH_HOST }} SSH_PORT: ${{ secrets.SSH_PORT || 22 }} SSH_USER: ${{ secrets.SSH_USER }} working-directory: /tmp/volunteer-deploy run: | PORT="${SSH_PORT:-22}" ssh -p $PORT $SSH_USER@$SSH_HOST "mkdir -p /opt/volunteer/app /opt/volunteer/data" scp -P $PORT -r deploy-pkg/app/* $SSH_USER@$SSH_HOST:/opt/volunteer/app/ scp -P $PORT deploy-pkg/docker-compose.yml $SSH_USER@$SSH_HOST:/opt/volunteer/docker-compose.yml ssh -p $PORT $SSH_USER@$SSH_HOST "cd /opt/volunteer && (docker compose down || true) && docker compose up -d --force-recreate && sleep 3 && docker compose ps" - name: Health check env: SSH_HOST: ${{ secrets.SSH_HOST }} SSH_PORT: ${{ secrets.SSH_PORT || 22 }} SSH_USER: ${{ secrets.SSH_USER }} run: | PORT="${SSH_PORT:-22}" ssh -p $PORT $SSH_USER@$SSH_HOST "for i in 1 2 3 4 5 6 7 8; do if curl -fsS http://localhost:3000/u > /dev/null; then echo 'Service OK'; exit 0; fi; echo Wait...; sleep 3; done; echo 'Service FAIL'; exit 1"