chore(deps): update transitive patch releases #5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 🚀 Deploy | |
| # On every push to main: run the CI gate first, then deploy to the Debian server | |
| # over SSH and restart the systemd unit. Can also be triggered manually via | |
| # "Run workflow". | |
| on: | |
| push: | |
| branches: [main] | |
| # Documentation and meta changes must not trigger a production redeploy. | |
| # graphify-out/ belongs in this list for the same reason: the codebase graph | |
| # is versioned but never executed, so a `graphify update` would otherwise | |
| # restart the live bot for nothing. | |
| paths-ignore: | |
| - '**.md' | |
| - '.github/**' | |
| - '.gitignore' | |
| - 'graphify-out/**' | |
| - 'multibot.service' | |
| workflow_dispatch: | |
| # Never let two deploys touch the server at the same time. Not cancelling in | |
| # progress: a half-applied deploy is worse than a redundant one. | |
| concurrency: | |
| group: deploy-production | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| # Same checks pull requests get. Nothing reaches the server that fails to parse. | |
| verify: | |
| uses: ./.github/workflows/ci.yml | |
| deploy: | |
| needs: verify | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Deploy via SSH | |
| uses: appleboy/ssh-action@v1.2.5 | |
| with: | |
| host: ${{ secrets.DEPLOY_HOST }} | |
| username: ${{ secrets.DEPLOY_USER }} | |
| key: ${{ secrets.DEPLOY_SSH_KEY }} | |
| port: ${{ secrets.DEPLOY_PORT }} | |
| script: | | |
| set -euo pipefail | |
| REPO="https://github.com/MSK-Scripts/discord_multibot.git" | |
| DIR="/opt/discord_multibot" | |
| mkdir -p "$DIR" | |
| cd "$DIR" | |
| # Self-healing: initialize the directory as a git repo if needed and | |
| # hard-reset it onto origin/main. Works for the very first deploy | |
| # too, when $DIR was not a clone yet. | |
| git config --global --add safe.directory "$DIR" 2>/dev/null || true | |
| git init -q | |
| git remote get-url origin >/dev/null 2>&1 \ | |
| && git remote set-url origin "$REPO" \ | |
| || git remote add origin "$REPO" | |
| git fetch --depth=1 origin main | |
| git reset --hard origin/main | |
| # Deliberately `clean -df` and NOT `-dfx`: without -x, git leaves | |
| # everything listed in .gitignore alone. That is exactly what has to | |
| # survive a deploy here: .env, data/ with points.json and the | |
| # database backups, assets/ with the terms PDF, node_modules/, the | |
| # log files, and bots/commands/commands/orders.js, which is | |
| # intentionally untracked and would otherwise be deleted on every | |
| # single deploy. | |
| # A new .gitignore entry is protected automatically this way. | |
| git clean -df | |
| # The production .env is never transferred through git. | |
| if [ ! -f .env ]; then | |
| echo "ERROR: $DIR/.env is missing. Create the production .env first (see README)." | |
| exit 1 | |
| fi | |
| # No devDependencies in this project, --omit=dev keeps it that way | |
| # should any ever be added. | |
| npm ci --omit=dev | |
| # The deploy runs as root, the service runs as discord:discord. | |
| # Without this, files would end up owned by root:root. .env is | |
| # restricted to the owner on top of that. | |
| chown -R discord:discord "$DIR" | |
| chmod 600 "$DIR/.env" | |
| # multibot.service itself is NOT installed from here. If the unit | |
| # changed, copy it to /etc/systemd/system and run daemon-reload by | |
| # hand, that is why it sits in paths-ignore above. | |
| # Clear a previous crash loop first. The unit has StartLimitBurst=5 | |
| # within 120s, and once that budget is spent systemd refuses to | |
| # start the service at all, even after the broken code is gone. | |
| # Without this, one bad deploy keeps every following deploy red. | |
| sudo systemctl reset-failed multibot || true | |
| sudo systemctl restart multibot | |
| sleep 5 | |
| # `systemctl status` exits 3 for a dead unit, which would abort the | |
| # script here under `set -e` and skip the diagnostics below. That is | |
| # exactly when the log output is needed, so swallow the exit code. | |
| sudo systemctl --no-pager status multibot | head -n 8 || true | |
| # Fail the workflow loudly if the bot died right after the restart, | |
| # instead of reporting a green deploy for a dead service. | |
| if ! systemctl is-active --quiet multibot; then | |
| echo "ERROR: multibot is not running after the restart. Last log lines:" | |
| journalctl -u multibot -n 60 --no-pager || true | |
| exit 1 | |
| fi | |
| echo "✅ Deployed $(git rev-parse --short HEAD) and multibot is running." |