name: Deploy Demo Server on: workflow_dispatch: # schedule: # - cron: '0 0 * * *' # Nightly at midnight jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.24' cache: true - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' cache-dependency-path: 'frontend-modern/package-lock.json' - name: Install frontend dependencies run: npm --prefix frontend-modern ci - name: Restore frontend build cache uses: actions/cache@v4 with: path: frontend-modern/dist key: frontend-build-${{ hashFiles('frontend-modern/package-lock.json', 'frontend-modern/src/**/*', 'frontend-modern/index.html', 'frontend-modern/postcss.config.cjs', 'frontend-modern/tailwind.config.cjs') }} - name: Build frontend run: | if [ -d "frontend-modern/dist" ] && [ -f "frontend-modern/dist/index.html" ]; then echo "Using cached frontend build"; else npm --prefix frontend-modern run build; fi # Prepare embedding directory rm -rf internal/api/frontend-modern mkdir -p internal/api/frontend-modern cp -r frontend-modern/dist internal/api/frontend-modern/ - name: Build static binary run: CGO_ENABLED=0 go build -ldflags="-s -w" -o pulse ./cmd/pulse/ - name: Tailscale uses: tailscale/github-action@v2 with: authkey: ${{ secrets.TS_AUTHKEY }} - name: Setup SSH run: | mkdir -p ~/.ssh echo "${{ secrets.DEMO_SERVER_SSH_KEY }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -H ${{ secrets.DEMO_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true - name: Deploy to server env: DEPLOY_HOST: ${{ secrets.DEMO_SERVER_HOST }} DEPLOY_USER: ${{ secrets.DEMO_SERVER_USER }} run: | # Clean up any stale files from previous runs ssh -o StrictHostKeyChecking=no ${DEPLOY_USER}@${DEPLOY_HOST} "rm -f /tmp/pulse-new; rm -rf /tmp/pulse-demo-test" || true # Upload new binary scp -o StrictHostKeyChecking=no pulse ${DEPLOY_USER}@${DEPLOY_HOST}:/tmp/pulse-new # Health check: Run on test port 8082 and verify # We use a subshell to background the process and then kill it after the check ssh -o StrictHostKeyChecking=no ${DEPLOY_USER}@${DEPLOY_HOST} " chmod +x /tmp/pulse-new && PULSE_DATA_DIR=/tmp/pulse-demo-test \ FRONTEND_PORT=8082 \ PULSE_MOCK_MODE=true \ PULSE_AUTH_USER=test \ PULSE_AUTH_PASS=test \ nohup /tmp/pulse-new > /tmp/demo-deploy-test.log 2>&1 & PID=\$! sleep 5 if curl -f http://127.0.0.1:8082/api/health; then echo 'Health check passed!' kill \$PID rm -rf /tmp/pulse-demo-test rm /tmp/demo-deploy-test.log else echo 'Health check failed! Error log:' cat /tmp/demo-deploy-test.log kill \$PID rm -rf /tmp/pulse-demo-test exit 1 fi " # Swap and restart production service ssh -o StrictHostKeyChecking=no ${DEPLOY_USER}@${DEPLOY_HOST} " sudo systemctl stop pulse && sudo mv /tmp/pulse-new /opt/pulse/bin/pulse && sudo systemctl start pulse " - name: Verify production run: | sleep 5 curl -f https://demo.pulserelay.pro/api/health